blob: 5ac2511804d27af3c271b2262532870e5d651a65 [file] [log] [blame]
Chris Craik2af46352012-11-26 18:30:17 -08001/*
Romain Guy7031ff62013-02-22 11:48:16 -08002 * Copyright (C) 2013 The Android Open Source Project
Chris Craik2af46352012-11-26 18:30:17 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
18#define ANDROID_HWUI_DISPLAY_OPERATION_H
19
Romain Guy7031ff62013-02-22 11:48:16 -080020#ifndef LOG_TAG
21 #define LOG_TAG "OpenGLRenderer"
22#endif
23
Chris Craik2af46352012-11-26 18:30:17 -080024#include <SkXfermode.h>
25
Chris Craik0776a602013-02-14 15:36:01 -080026#include <private/hwui/DrawGlInfo.h>
27
Chris Craik2af46352012-11-26 18:30:17 -080028#include "OpenGLRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070029#include "AssetAtlas.h"
Chris Craikc3566d02013-02-04 16:16:33 -080030#include "DeferredDisplayList.h"
Chris Craik2af46352012-11-26 18:30:17 -080031#include "DisplayListRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070032#include "UvMapper.h"
Chris Craik2af46352012-11-26 18:30:17 -080033#include "utils/LinearAllocator.h"
34
35#define CRASH() do { \
Romain Guy5216c3b2013-06-14 16:31:37 -070036 *(int *)(uintptr_t) 0xbbadbeef = 0; \
Chris Craik2af46352012-11-26 18:30:17 -080037 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
38} while(false)
39
Chris Craik2af46352012-11-26 18:30:17 -080040// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070041#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080042#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080043
Chris Craik2af46352012-11-26 18:30:17 -080044namespace android {
45namespace uirenderer {
46
47/**
48 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
49 * may be replayed to an OpenGLRenderer.
50 *
51 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
52 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
53 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
54 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
55 * never called as LinearAllocators are simply discarded, so no memory management should be done in
56 * this class.
57 */
58class DisplayListOp {
59public:
60 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
61 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
62 virtual ~DisplayListOp() { CRASH(); }
63 static void operator delete(void* ptr) { CRASH(); }
64 /** static void* operator new(size_t size); PURPOSELY OMITTED **/
65 static void* operator new(size_t size, LinearAllocator& allocator) {
66 return allocator.alloc(size);
67 }
68
69 enum OpLogFlag {
70 kOpLogFlag_Recurse = 0x1,
71 kOpLogFlag_JSON = 0x2 // TODO: add?
72 };
73
Chet Haasedd671592013-04-19 14:54:34 -070074 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
75 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080076
Chet Haasedd671592013-04-19 14:54:34 -070077 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
78 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080079
Chris Craikc5493fb2013-06-19 16:58:58 -070080 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080081
82 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
83 // point at the constants, but that seems to require a .cpp file
84 virtual const char* name() = 0;
Chris Craikff785832013-03-08 13:12:16 -080085
86 /**
87 * Stores the relevant canvas state of the object between deferral and replay (if the canvas
88 * state supports being stored) See OpenGLRenderer::simpleClipAndState()
89 *
90 * TODO: don't reserve space for StateOps that won't be deferred
91 */
92 DeferredDisplayState state;
93
Chris Craik2af46352012-11-26 18:30:17 -080094};
95
96class StateOp : public DisplayListOp {
97public:
98 StateOp() {};
99
100 virtual ~StateOp() {}
101
Chet Haasedd671592013-04-19 14:54:34 -0700102 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
103 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800104 // default behavior only affects immediate, deferrable state, issue directly to renderer
105 applyState(deferStruct.mRenderer, saveCount);
106 }
107
Chris Craikc3566d02013-02-04 16:16:33 -0800108 /**
109 * State operations are applied directly to the renderer, but can cause the deferred drawing op
110 * list to flush
111 */
Chet Haasedd671592013-04-19 14:54:34 -0700112 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
113 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800114 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800115 }
116
Chris Craik7273daa2013-03-28 11:25:24 -0700117 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800118};
119
120class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800121friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800122public:
123 DrawOp(SkPaint* paint)
124 : mPaint(paint), mQuickRejected(false) {}
125
Chet Haasedd671592013-04-19 14:54:34 -0700126 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
127 bool useQuickReject) {
128 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800129 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800130 }
131
Chris Craikd72b73c2013-06-17 13:52:06 -0700132 if (getLocalBounds(state.mBounds)) {
133 // valid empty bounds, don't bother deferring
134 if (state.mBounds.isEmpty()) return;
135 } else {
Chris Craikc3566d02013-02-04 16:16:33 -0800136 // empty bounds signify bounds can't be calculated
137 state.mBounds.setEmpty();
138 }
139
Chris Craikff785832013-03-08 13:12:16 -0800140 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800141 }
142
Chet Haasedd671592013-04-19 14:54:34 -0700143 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
144 bool useQuickReject) {
145 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800146 return;
147 }
148
Chris Craik527a3aa2013-03-04 10:19:31 -0800149 replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800150 }
151
Chris Craik527a3aa2013-03-04 10:19:31 -0800152 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800153
Chris Craik527a3aa2013-03-04 10:19:31 -0800154 /**
155 * Draw multiple instances of an operation, must be overidden for operations that merge
156 *
157 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
158 * and pure translation transformations. Other guarantees of similarity should be enforced by
159 * reducing which operations are tagged as mergeable.
160 */
161 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
162 const Vector<DrawOp*>& ops, const Rect& bounds) {
163 status_t status = DrawGlInfo::kStatusDone;
164 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700165 renderer.restoreDisplayState(ops[i]->state, true);
Chris Craik527a3aa2013-03-04 10:19:31 -0800166 status |= ops[i]->applyDraw(renderer, dirty);
167 }
168 return status;
169 }
170
Chris Craik28ce94a2013-05-31 11:38:03 -0700171 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800172 * When this method is invoked the state field is initialized to have the
173 * final rendering state. We can thus use it to process data as it will be
174 * used at draw time.
175 *
176 * Additionally, this method allows subclasses to provide defer-time preferences for batching
177 * and merging.
178 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700179 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800180 */
Chris Craik28ce94a2013-05-31 11:38:03 -0700181 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {}
Romain Guy0f667532013-03-01 14:31:04 -0800182
Chris Craik2af46352012-11-26 18:30:17 -0800183 // returns true if bounds exist
184 virtual bool getLocalBounds(Rect& localBounds) { return false; }
185
186 // TODO: better refine localbounds usage
187 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
188 bool getQuickRejected() { return mQuickRejected; }
189
Chris Craik527a3aa2013-03-04 10:19:31 -0800190 inline int getPaintAlpha() {
191 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800192 }
193
Chris Craik527a3aa2013-03-04 10:19:31 -0800194 inline float strokeWidthOutset() {
Chris Craike7c69c62013-04-03 09:55:48 -0700195 float width = mPaint->getStrokeWidth();
196 if (width == 0) return 0.5f; // account for hairline
197 return width * 0.5f;
198 }
Chris Craikc3566d02013-02-04 16:16:33 -0800199
Chris Craik2af46352012-11-26 18:30:17 -0800200protected:
Chris Craika08f95c2013-03-15 17:24:33 -0700201 SkPaint* getPaint(OpenGLRenderer& renderer) {
202 return renderer.filterPaint(mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800203 }
204
Chris Craik28ce94a2013-05-31 11:38:03 -0700205 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
206 // coordinates, and that paint's alpha is used
207 inline bool isOpaqueOverBounds() {
208 // ensure that local bounds cover mapped bounds
209 if (!state.mMatrix.isSimple()) return false;
210
211 // check state/paint for transparency
212 if (state.mDrawModifiers.mShader ||
213 state.mAlpha != 1.0f ||
214 (mPaint && mPaint->getAlpha() != 0xFF)) return false;
215
216 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
217 return (mode == SkXfermode::kSrcOver_Mode ||
218 mode == SkXfermode::kSrc_Mode);
219
220 }
221
Chris Craik2af46352012-11-26 18:30:17 -0800222 SkPaint* mPaint; // should be accessed via getPaint() when applying
223 bool mQuickRejected;
224};
225
226class DrawBoundedOp : public DrawOp {
227public:
228 DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
229 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
230
Chris Craik41541822013-05-03 16:35:54 -0700231 DrawBoundedOp(const Rect& localBounds, SkPaint* paint)
232 : DrawOp(paint), mLocalBounds(localBounds) {}
233
Chris Craik5d116762013-02-19 17:49:31 -0800234 // Calculates bounds as smallest rect encompassing all points
235 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
236 // subclass' constructor)
237 DrawBoundedOp(const float* points, int count, SkPaint* paint)
238 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
239 for (int i = 2; i < count; i += 2) {
240 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
241 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
242 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
243 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
244 }
245 }
246
247 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craik2af46352012-11-26 18:30:17 -0800248 DrawBoundedOp(SkPaint* paint)
249 : DrawOp(paint) {}
250
251 bool getLocalBounds(Rect& localBounds) {
252 localBounds.set(mLocalBounds);
253 return true;
254 }
255
256protected:
257 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
258};
259
260///////////////////////////////////////////////////////////////////////////////
261// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
262// not directly draw or alter output
263///////////////////////////////////////////////////////////////////////////////
264
265class SaveOp : public StateOp {
Chris Craikff785832013-03-08 13:12:16 -0800266 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800267public:
268 SaveOp(int flags)
269 : mFlags(flags) {}
270
Chet Haasedd671592013-04-19 14:54:34 -0700271 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
272 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800273 int newSaveCount = deferStruct.mRenderer.save(mFlags);
274 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
275 }
276
Chris Craik7273daa2013-03-28 11:25:24 -0700277 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800278 renderer.save(mFlags);
279 }
280
Chris Craikc5493fb2013-06-19 16:58:58 -0700281 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800282 OP_LOG("Save flags %x", mFlags);
283 }
284
285 virtual const char* name() { return "Save"; }
286
Chris Craikff785832013-03-08 13:12:16 -0800287 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800288private:
Chris Craikff785832013-03-08 13:12:16 -0800289 SaveOp() {}
290 DisplayListOp* reinit(int flags) {
291 mFlags = flags;
292 return this;
293 }
294
Chris Craik2af46352012-11-26 18:30:17 -0800295 int mFlags;
296};
297
298class RestoreToCountOp : public StateOp {
Chris Craikff785832013-03-08 13:12:16 -0800299 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800300public:
301 RestoreToCountOp(int count)
302 : mCount(count) {}
303
Chet Haasedd671592013-04-19 14:54:34 -0700304 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
305 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700306 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
307 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800308 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800309 }
310
Chris Craik7273daa2013-03-28 11:25:24 -0700311 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800312 renderer.restoreToCount(saveCount + mCount);
313 }
314
Chris Craikc5493fb2013-06-19 16:58:58 -0700315 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800316 OP_LOG("Restore to count %d", mCount);
317 }
318
319 virtual const char* name() { return "RestoreToCount"; }
320
321private:
Chris Craikff785832013-03-08 13:12:16 -0800322 RestoreToCountOp() {}
323 DisplayListOp* reinit(int count) {
324 mCount = count;
325 return this;
326 }
327
Chris Craik2af46352012-11-26 18:30:17 -0800328 int mCount;
329};
330
331class SaveLayerOp : public StateOp {
Chris Craikff785832013-03-08 13:12:16 -0800332 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800333public:
Chris Craikff785832013-03-08 13:12:16 -0800334 SaveLayerOp(float left, float top, float right, float bottom,
335 int alpha, SkXfermode::Mode mode, int flags)
336 : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
337
Chet Haasedd671592013-04-19 14:54:34 -0700338 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
339 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800340 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700341 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800342 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700343
344 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
345 // setup the snapshot for deferral, and re-issue the op at flush time
346 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
347 mAlpha, mMode, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800348 }
Chris Craik2af46352012-11-26 18:30:17 -0800349
Chris Craik7273daa2013-03-28 11:25:24 -0700350 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800351 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
Chris Craik2af46352012-11-26 18:30:17 -0800352 }
353
Chris Craikc5493fb2013-06-19 16:58:58 -0700354 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800355 OP_LOG("SaveLayer%s of area " RECT_STRING,
356 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800357 }
358
Chris Craikff785832013-03-08 13:12:16 -0800359 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
360
361 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800362
363private:
Chris Craikff785832013-03-08 13:12:16 -0800364 // Special case, reserved for direct DisplayList usage
365 SaveLayerOp() {}
366 DisplayListOp* reinit(float left, float top, float right, float bottom,
367 int alpha, SkXfermode::Mode mode, int flags) {
368 mArea.set(left, top, right, bottom);
369 mAlpha = alpha;
370 mMode = mode;
371 mFlags = flags;
372 return this;
Chris Craik2af46352012-11-26 18:30:17 -0800373 }
374
Chris Craikc5493fb2013-06-19 16:58:58 -0700375 bool isSaveLayerAlpha() const { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
Chris Craik2af46352012-11-26 18:30:17 -0800376 Rect mArea;
377 int mAlpha;
Chris Craikff785832013-03-08 13:12:16 -0800378 SkXfermode::Mode mMode;
Chris Craik2af46352012-11-26 18:30:17 -0800379 int mFlags;
380};
381
382class TranslateOp : public StateOp {
383public:
384 TranslateOp(float dx, float dy)
385 : mDx(dx), mDy(dy) {}
386
Chris Craik7273daa2013-03-28 11:25:24 -0700387 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800388 renderer.translate(mDx, mDy);
389 }
390
Chris Craikc5493fb2013-06-19 16:58:58 -0700391 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800392 OP_LOG("Translate by %f %f", mDx, mDy);
393 }
394
395 virtual const char* name() { return "Translate"; }
396
397private:
398 float mDx;
399 float mDy;
400};
401
402class RotateOp : public StateOp {
403public:
404 RotateOp(float degrees)
405 : mDegrees(degrees) {}
406
Chris Craik7273daa2013-03-28 11:25:24 -0700407 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800408 renderer.rotate(mDegrees);
409 }
410
Chris Craikc5493fb2013-06-19 16:58:58 -0700411 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800412 OP_LOG("Rotate by %f degrees", mDegrees);
413 }
414
415 virtual const char* name() { return "Rotate"; }
416
417private:
418 float mDegrees;
419};
420
421class ScaleOp : public StateOp {
422public:
423 ScaleOp(float sx, float sy)
424 : mSx(sx), mSy(sy) {}
425
Chris Craik7273daa2013-03-28 11:25:24 -0700426 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800427 renderer.scale(mSx, mSy);
428 }
429
Chris Craikc5493fb2013-06-19 16:58:58 -0700430 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800431 OP_LOG("Scale by %f %f", mSx, mSy);
432 }
433
434 virtual const char* name() { return "Scale"; }
435
436private:
437 float mSx;
438 float mSy;
439};
440
441class SkewOp : public StateOp {
442public:
443 SkewOp(float sx, float sy)
444 : mSx(sx), mSy(sy) {}
445
Chris Craik7273daa2013-03-28 11:25:24 -0700446 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800447 renderer.skew(mSx, mSy);
448 }
449
Chris Craikc5493fb2013-06-19 16:58:58 -0700450 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800451 OP_LOG("Skew by %f %f", mSx, mSy);
452 }
453
454 virtual const char* name() { return "Skew"; }
455
456private:
457 float mSx;
458 float mSy;
459};
460
461class SetMatrixOp : public StateOp {
462public:
463 SetMatrixOp(SkMatrix* matrix)
464 : mMatrix(matrix) {}
465
Chris Craik7273daa2013-03-28 11:25:24 -0700466 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800467 renderer.setMatrix(mMatrix);
468 }
469
Chris Craikc5493fb2013-06-19 16:58:58 -0700470 virtual void output(int level, uint32_t logFlags) const {
Romain Guy4e7b7722013-07-16 13:47:01 -0700471 if (mMatrix) {
472 OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
473 } else {
474 OP_LOGS("SetMatrix (reset)");
475 }
Chris Craik2af46352012-11-26 18:30:17 -0800476 }
477
478 virtual const char* name() { return "SetMatrix"; }
479
480private:
481 SkMatrix* mMatrix;
482};
483
484class ConcatMatrixOp : public StateOp {
485public:
486 ConcatMatrixOp(SkMatrix* matrix)
487 : mMatrix(matrix) {}
488
Chris Craik7273daa2013-03-28 11:25:24 -0700489 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800490 renderer.concatMatrix(mMatrix);
491 }
492
Chris Craikc5493fb2013-06-19 16:58:58 -0700493 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800494 OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
495 }
496
497 virtual const char* name() { return "ConcatMatrix"; }
498
499private:
500 SkMatrix* mMatrix;
501};
502
Chris Craikff785832013-03-08 13:12:16 -0800503class ClipOp : public StateOp {
504public:
505 ClipOp(SkRegion::Op op) : mOp(op) {}
506
Chet Haasedd671592013-04-19 14:54:34 -0700507 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
508 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800509 // NOTE: must defer op BEFORE applying state, since it may read clip
510 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
511
512 // TODO: Can we avoid applying complex clips at defer time?
513 applyState(deferStruct.mRenderer, saveCount);
514 }
515
516 bool canCauseComplexClip() {
517 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
518 }
519
520protected:
521 ClipOp() {}
522 virtual bool isRect() { return false; }
523
524 SkRegion::Op mOp;
525};
526
527class ClipRectOp : public ClipOp {
528 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800529public:
530 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800531 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800532
Chris Craik7273daa2013-03-28 11:25:24 -0700533 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800534 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
535 }
536
Chris Craikc5493fb2013-06-19 16:58:58 -0700537 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800538 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
539 }
540
541 virtual const char* name() { return "ClipRect"; }
542
Chris Craikff785832013-03-08 13:12:16 -0800543protected:
544 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800545
Chris Craik2af46352012-11-26 18:30:17 -0800546private:
Chris Craikff785832013-03-08 13:12:16 -0800547 ClipRectOp() {}
548 DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
549 mOp = op;
550 mArea.set(left, top, right, bottom);
551 return this;
Chris Craikb98a0162013-02-21 11:30:22 -0800552 }
Chris Craikff785832013-03-08 13:12:16 -0800553
Chris Craik2af46352012-11-26 18:30:17 -0800554 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800555};
556
Chris Craikff785832013-03-08 13:12:16 -0800557class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800558public:
559 ClipPathOp(SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800560 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800561
Chris Craik7273daa2013-03-28 11:25:24 -0700562 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800563 renderer.clipPath(mPath, mOp);
564 }
565
Chris Craikc5493fb2013-06-19 16:58:58 -0700566 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800567 SkRect bounds = mPath->getBounds();
568 OP_LOG("ClipPath bounds " RECT_STRING,
569 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
570 }
571
572 virtual const char* name() { return "ClipPath"; }
573
574private:
575 SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800576};
577
Chris Craikff785832013-03-08 13:12:16 -0800578class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800579public:
580 ClipRegionOp(SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800581 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800582
Chris Craik7273daa2013-03-28 11:25:24 -0700583 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800584 renderer.clipRegion(mRegion, mOp);
585 }
586
Chris Craikc5493fb2013-06-19 16:58:58 -0700587 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800588 SkIRect bounds = mRegion->getBounds();
589 OP_LOG("ClipRegion bounds %d %d %d %d",
590 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
591 }
592
593 virtual const char* name() { return "ClipRegion"; }
594
595private:
596 SkRegion* mRegion;
597 SkRegion::Op mOp;
598};
599
600class ResetShaderOp : public StateOp {
601public:
Chris Craik7273daa2013-03-28 11:25:24 -0700602 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800603 renderer.resetShader();
604 }
605
Chris Craikc5493fb2013-06-19 16:58:58 -0700606 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800607 OP_LOGS("ResetShader");
608 }
609
610 virtual const char* name() { return "ResetShader"; }
611};
612
613class SetupShaderOp : public StateOp {
614public:
615 SetupShaderOp(SkiaShader* shader)
616 : mShader(shader) {}
Chris Craik7273daa2013-03-28 11:25:24 -0700617 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800618 renderer.setupShader(mShader);
619 }
620
Chris Craikc5493fb2013-06-19 16:58:58 -0700621 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800622 OP_LOG("SetupShader, shader %p", mShader);
623 }
624
625 virtual const char* name() { return "SetupShader"; }
626
627private:
628 SkiaShader* mShader;
629};
630
631class ResetColorFilterOp : public StateOp {
632public:
Chris Craik7273daa2013-03-28 11:25:24 -0700633 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800634 renderer.resetColorFilter();
635 }
636
Chris Craikc5493fb2013-06-19 16:58:58 -0700637 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800638 OP_LOGS("ResetColorFilter");
639 }
640
641 virtual const char* name() { return "ResetColorFilter"; }
642};
643
644class SetupColorFilterOp : public StateOp {
645public:
646 SetupColorFilterOp(SkiaColorFilter* colorFilter)
647 : mColorFilter(colorFilter) {}
648
Chris Craik7273daa2013-03-28 11:25:24 -0700649 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800650 renderer.setupColorFilter(mColorFilter);
651 }
652
Chris Craikc5493fb2013-06-19 16:58:58 -0700653 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800654 OP_LOG("SetupColorFilter, filter %p", mColorFilter);
655 }
656
657 virtual const char* name() { return "SetupColorFilter"; }
658
659private:
660 SkiaColorFilter* mColorFilter;
661};
662
663class ResetShadowOp : public StateOp {
664public:
Chris Craik7273daa2013-03-28 11:25:24 -0700665 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800666 renderer.resetShadow();
667 }
668
Chris Craikc5493fb2013-06-19 16:58:58 -0700669 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800670 OP_LOGS("ResetShadow");
671 }
672
673 virtual const char* name() { return "ResetShadow"; }
674};
675
676class SetupShadowOp : public StateOp {
677public:
678 SetupShadowOp(float radius, float dx, float dy, int color)
679 : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
680
Chris Craik7273daa2013-03-28 11:25:24 -0700681 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800682 renderer.setupShadow(mRadius, mDx, mDy, mColor);
683 }
684
Chris Craikc5493fb2013-06-19 16:58:58 -0700685 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800686 OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
687 }
688
689 virtual const char* name() { return "SetupShadow"; }
690
691private:
692 float mRadius;
693 float mDx;
694 float mDy;
695 int mColor;
696};
697
698class ResetPaintFilterOp : public StateOp {
699public:
Chris Craik7273daa2013-03-28 11:25:24 -0700700 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800701 renderer.resetPaintFilter();
702 }
703
Chris Craikc5493fb2013-06-19 16:58:58 -0700704 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800705 OP_LOGS("ResetPaintFilter");
706 }
707
708 virtual const char* name() { return "ResetPaintFilter"; }
709};
710
711class SetupPaintFilterOp : public StateOp {
712public:
713 SetupPaintFilterOp(int clearBits, int setBits)
714 : mClearBits(clearBits), mSetBits(setBits) {}
715
Chris Craik7273daa2013-03-28 11:25:24 -0700716 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800717 renderer.setupPaintFilter(mClearBits, mSetBits);
718 }
719
Chris Craikc5493fb2013-06-19 16:58:58 -0700720 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800721 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
722 }
723
724 virtual const char* name() { return "SetupPaintFilter"; }
725
726private:
727 int mClearBits;
728 int mSetBits;
729};
730
Chris Craik2af46352012-11-26 18:30:17 -0800731///////////////////////////////////////////////////////////////////////////////
732// DRAW OPERATIONS - these are operations that can draw to the canvas's device
733///////////////////////////////////////////////////////////////////////////////
734
735class DrawBitmapOp : public DrawBoundedOp {
736public:
737 DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
Romain Guy3b748a42013-04-17 18:54:38 -0700738 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700739 mBitmap(bitmap), mAtlas(Caches::getInstance().assetAtlas) {
740 mEntry = mAtlas.getEntry(bitmap);
741 if (mEntry) {
742 mEntryGenerationId = mAtlas.getGenerationId();
743 mUvMapper = mEntry->uvMapper;
744 }
Romain Guy3b748a42013-04-17 18:54:38 -0700745 }
Chris Craik2af46352012-11-26 18:30:17 -0800746
Chris Craik527a3aa2013-03-04 10:19:31 -0800747 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -0700748 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
749 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800750 }
751
Romain Guy55b6f952013-06-27 15:27:09 -0700752 AssetAtlas::Entry* getAtlasEntry() {
753 // The atlas entry is stale, let's get a new one
754 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
755 mEntryGenerationId = mAtlas.getGenerationId();
756 mEntry = mAtlas.getEntry(mBitmap);
757 mUvMapper = mEntry->uvMapper;
758 }
759 return mEntry;
760 }
761
Chris Craik527a3aa2013-03-04 10:19:31 -0800762#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
763 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
764 texCoordsRect.xDim, texCoordsRect.yDim)
765
Romain Guy03c00b52013-06-20 18:30:28 -0700766 /**
767 * This multi-draw operation builds a mesh on the stack by generating a quad
768 * for each bitmap in the batch. This method is also responsible for dirtying
769 * the current layer, if any.
770 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800771 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
772 const Vector<DrawOp*>& ops, const Rect& bounds) {
773 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -0800774 TextureVertex vertices[6 * ops.size()];
775 TextureVertex* vertex = &vertices[0];
776
Romain Guy03c00b52013-06-20 18:30:28 -0700777 const bool hasLayer = renderer.hasLayer();
Romain Guy2db5e992013-05-21 15:29:59 -0700778 bool transformed = false;
779
Romain Guy3b748a42013-04-17 18:54:38 -0700780 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
781 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800782 for (unsigned int i = 0; i < ops.size(); i++) {
783 const Rect& opBounds = ops[i]->state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700784 // When we reach multiDraw(), the matrix can be either
785 // pureTranslate or simple (translate and/or scale).
786 // If the matrix is not pureTranslate, then we have a scale
787 if (!ops[i]->state.mMatrix.isPureTranslate()) transformed = true;
Romain Guy3b748a42013-04-17 18:54:38 -0700788
789 Rect texCoords(0, 0, 1, 1);
790 ((DrawBitmapOp*) ops[i])->mUvMapper.map(texCoords);
791
Chris Craik527a3aa2013-03-04 10:19:31 -0800792 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
793 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
794 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
795
796 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
797 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
798 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700799
800 if (hasLayer) {
801 const Rect& dirty = ops[i]->state.mBounds;
802 renderer.dirtyLayer(dirty.left, dirty.top, dirty.right, dirty.bottom);
803 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800804 }
805
Romain Guy55b6f952013-06-27 15:27:09 -0700806 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Romain Guy2db5e992013-05-21 15:29:59 -0700807 transformed, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800808 }
809
Chris Craikc5493fb2013-06-19 16:58:58 -0700810 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800811 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
812 }
813
814 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800815
Chris Craik28ce94a2013-05-31 11:38:03 -0700816 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
817 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700818 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700819
Chris Craik28ce94a2013-05-31 11:38:03 -0700820 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
821 // MergingDrawBatch::canMergeWith()
822 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
823 deferInfo.mergeable = state.mMatrix.isSimple() && !state.mClipSideFlags &&
824 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
825 (mBitmap->getConfig() != SkBitmap::kA8_Config);
Chris Craikc3566d02013-02-04 16:16:33 -0800826 }
Chris Craik2af46352012-11-26 18:30:17 -0800827
Chris Craik527a3aa2013-03-04 10:19:31 -0800828 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800829protected:
830 SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700831 const AssetAtlas& mAtlas;
832 uint32_t mEntryGenerationId;
833 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700834 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800835};
836
837class DrawBitmapMatrixOp : public DrawBoundedOp {
838public:
839 DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
840 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
841 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
842 const mat4 transform(*matrix);
843 transform.mapRect(mLocalBounds);
844 }
845
Chris Craik527a3aa2013-03-04 10:19:31 -0800846 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800847 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
848 }
849
Chris Craikc5493fb2013-06-19 16:58:58 -0700850 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800851 OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
852 }
853
Chris Craik527a3aa2013-03-04 10:19:31 -0800854 virtual const char* name() { return "DrawBitmapMatrix"; }
855
Chris Craik28ce94a2013-05-31 11:38:03 -0700856 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
857 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800858 }
Chris Craik2af46352012-11-26 18:30:17 -0800859
860private:
861 SkBitmap* mBitmap;
862 SkMatrix* mMatrix;
863};
864
865class DrawBitmapRectOp : public DrawBoundedOp {
866public:
867 DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
868 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
869 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
870 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
871
Chris Craik527a3aa2013-03-04 10:19:31 -0800872 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800873 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
874 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
875 getPaint(renderer));
876 }
877
Chris Craikc5493fb2013-06-19 16:58:58 -0700878 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800879 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
880 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
881 }
882
883 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800884
Chris Craik28ce94a2013-05-31 11:38:03 -0700885 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
886 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800887 }
Chris Craik2af46352012-11-26 18:30:17 -0800888
889private:
890 SkBitmap* mBitmap;
891 Rect mSrc;
892};
893
894class DrawBitmapDataOp : public DrawBitmapOp {
895public:
896 DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
897 : DrawBitmapOp(bitmap, left, top, paint) {}
898
Chris Craik527a3aa2013-03-04 10:19:31 -0800899 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800900 return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
901 mLocalBounds.top, getPaint(renderer));
902 }
903
Chris Craikc5493fb2013-06-19 16:58:58 -0700904 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800905 OP_LOG("Draw bitmap %p", mBitmap);
906 }
907
908 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800909
Chris Craik28ce94a2013-05-31 11:38:03 -0700910 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
911 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800912 }
Chris Craik2af46352012-11-26 18:30:17 -0800913};
914
Chris Craik5d116762013-02-19 17:49:31 -0800915class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800916public:
917 DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
918 float* vertices, int* colors, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800919 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
920 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800921 mVertices(vertices), mColors(colors) {}
922
Chris Craik527a3aa2013-03-04 10:19:31 -0800923 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800924 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
925 mVertices, mColors, getPaint(renderer));
926 }
927
Chris Craikc5493fb2013-06-19 16:58:58 -0700928 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800929 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
930 }
931
932 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800933
Chris Craik28ce94a2013-05-31 11:38:03 -0700934 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
935 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800936 }
Chris Craik2af46352012-11-26 18:30:17 -0800937
938private:
939 SkBitmap* mBitmap;
940 int mMeshWidth;
941 int mMeshHeight;
942 float* mVertices;
943 int* mColors;
944};
945
946class DrawPatchOp : public DrawBoundedOp {
947public:
Romain Guy3b748a42013-04-17 18:54:38 -0700948 DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch,
Romain Guy03c00b52013-06-20 18:30:28 -0700949 float left, float top, float right, float bottom, SkPaint* paint)
950 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700951 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
952 mAtlas(Caches::getInstance().assetAtlas) {
953 mEntry = mAtlas.getEntry(bitmap);
954 if (mEntry) {
955 mEntryGenerationId = mAtlas.getGenerationId();
956 }
Romain Guy3b748a42013-04-17 18:54:38 -0700957 };
Chris Craik2af46352012-11-26 18:30:17 -0800958
Romain Guy55b6f952013-06-27 15:27:09 -0700959 AssetAtlas::Entry* getAtlasEntry() {
960 // The atlas entry is stale, let's get a new one
961 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
962 mEntryGenerationId = mAtlas.getGenerationId();
963 mEntry = mAtlas.getEntry(mBitmap);
964 }
965 return mEntry;
966 }
967
Romain Guy03c00b52013-06-20 18:30:28 -0700968 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700969 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
970 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700971 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700972 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700973 mGenerationId = cache.getGenerationId();
974 }
Romain Guy03c00b52013-06-20 18:30:28 -0700975 return mMesh;
976 }
977
978 /**
979 * This multi-draw operation builds an indexed mesh on the stack by copying
980 * and transforming the vertices of each 9-patch in the batch. This method
981 * is also responsible for dirtying the current layer, if any.
982 */
983 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
984 const Vector<DrawOp*>& ops, const Rect& bounds) {
985 renderer.restoreDisplayState(state, true);
986
987 // Batches will usually contain a small number of items so it's
988 // worth performing a first iteration to count the exact number
989 // of vertices we need in the new mesh
990 uint32_t totalVertices = 0;
991 for (unsigned int i = 0; i < ops.size(); i++) {
992 totalVertices += ((DrawPatchOp*) ops[i])->getMesh(renderer)->verticesCount;
993 }
994
995 const bool hasLayer = renderer.hasLayer();
996
997 uint32_t indexCount = 0;
998
999 TextureVertex vertices[totalVertices];
1000 TextureVertex* vertex = &vertices[0];
1001
1002 // Create a mesh that contains the transformed vertices for all the
1003 // 9-patch objects that are part of the batch. Note that onDefer()
1004 // enforces ops drawn by this function to have a pure translate or
1005 // identity matrix
1006 for (unsigned int i = 0; i < ops.size(); i++) {
1007 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i];
1008 const Patch* opMesh = patchOp->getMesh(renderer);
1009 uint32_t vertexCount = opMesh->verticesCount;
1010 if (vertexCount == 0) continue;
1011
1012 // We use the bounds to know where to translate our vertices
1013 // Using patchOp->state.mBounds wouldn't work because these
1014 // bounds are clipped
1015 const float tx = (int) floorf(patchOp->state.mMatrix.getTranslateX() +
1016 patchOp->mLocalBounds.left + 0.5f);
1017 const float ty = (int) floorf(patchOp->state.mMatrix.getTranslateY() +
1018 patchOp->mLocalBounds.top + 0.5f);
1019
1020 // Copy & transform all the vertices for the current operation
1021 TextureVertex* opVertices = opMesh->vertices;
1022 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
1023 TextureVertex::set(vertex++,
1024 opVertices->position[0] + tx, opVertices->position[1] + ty,
1025 opVertices->texture[0], opVertices->texture[1]);
1026 }
1027
1028 // Dirty the current layer if possible. When the 9-patch does not
1029 // contain empty quads we can take a shortcut and simply set the
1030 // dirty rect to the object's bounds.
1031 if (hasLayer) {
1032 if (!opMesh->hasEmptyQuads) {
1033 renderer.dirtyLayer(tx, ty,
1034 tx + patchOp->mLocalBounds.getWidth(),
1035 ty + patchOp->mLocalBounds.getHeight());
1036 } else {
1037 const size_t count = opMesh->quads.size();
1038 for (size_t i = 0; i < count; i++) {
1039 const Rect& quadBounds = opMesh->quads[i];
1040 const float x = tx + quadBounds.left;
1041 const float y = ty + quadBounds.top;
1042 renderer.dirtyLayer(x, y,
1043 x + quadBounds.getWidth(), y + quadBounds.getHeight());
1044 }
1045 }
1046 }
1047
1048 indexCount += opMesh->indexCount;
1049 }
1050
Romain Guy55b6f952013-06-27 15:27:09 -07001051 return renderer.drawPatches(mBitmap, getAtlasEntry(),
1052 &vertices[0], indexCount, getPaint(renderer));
Romain Guy03c00b52013-06-20 18:30:28 -07001053 }
1054
1055 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -07001056 // We're not calling the public variant of drawPatch() here
1057 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy55b6f952013-06-27 15:27:09 -07001058 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -07001059 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
1060 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -08001061 }
1062
Chris Craikc5493fb2013-06-19 16:58:58 -07001063 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001064 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
1065 }
1066
1067 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -08001068
Chris Craik28ce94a2013-05-31 11:38:03 -07001069 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1070 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy55b6f952013-06-27 15:27:09 -07001071 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -07001072 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
1073 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy5216c3b2013-06-14 16:31:37 -07001074 deferInfo.opaqueOverBounds = isOpaqueOverBounds() && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -08001075 }
Chris Craik2af46352012-11-26 18:30:17 -08001076
1077private:
1078 SkBitmap* mBitmap;
Romain Guy3b748a42013-04-17 18:54:38 -07001079 Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -07001080
Romain Guy4c2547f2013-06-11 16:19:24 -07001081 uint32_t mGenerationId;
1082 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -07001083
Romain Guy55b6f952013-06-27 15:27:09 -07001084 const AssetAtlas& mAtlas;
1085 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -07001086 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -08001087};
1088
1089class DrawColorOp : public DrawOp {
1090public:
1091 DrawColorOp(int color, SkXfermode::Mode mode)
1092 : DrawOp(0), mColor(color), mMode(mode) {};
1093
Chris Craik527a3aa2013-03-04 10:19:31 -08001094 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001095 return renderer.drawColor(mColor, mMode);
1096 }
1097
Chris Craikc5493fb2013-06-19 16:58:58 -07001098 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001099 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
1100 }
1101
1102 virtual const char* name() { return "DrawColor"; }
1103
1104private:
1105 int mColor;
1106 SkXfermode::Mode mMode;
1107};
1108
1109class DrawStrokableOp : public DrawBoundedOp {
1110public:
1111 DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
1112 : DrawBoundedOp(left, top, right, bottom, paint) {};
1113
1114 bool getLocalBounds(Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001115 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001116 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001117 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001118 }
1119 return true;
1120 }
Chris Craikc3566d02013-02-04 16:16:33 -08001121
Chris Craik28ce94a2013-05-31 11:38:03 -07001122 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Chris Craikc3566d02013-02-04 16:16:33 -08001123 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001124 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001125 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001126 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001127 DeferredDisplayList::kOpBatch_AlphaVertices :
1128 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001129 }
Chris Craikc3566d02013-02-04 16:16:33 -08001130 }
Chris Craik2af46352012-11-26 18:30:17 -08001131};
1132
1133class DrawRectOp : public DrawStrokableOp {
1134public:
1135 DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
1136 : DrawStrokableOp(left, top, right, bottom, paint) {}
1137
Chris Craik527a3aa2013-03-04 10:19:31 -08001138 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001139 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1140 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1141 }
1142
Chris Craikc5493fb2013-06-19 16:58:58 -07001143 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001144 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
1145 }
1146
Chris Craik28ce94a2013-05-31 11:38:03 -07001147 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1148 DrawStrokableOp::onDefer(renderer, deferInfo);
1149 deferInfo.opaqueOverBounds = isOpaqueOverBounds() &&
1150 mPaint->getStyle() == SkPaint::kFill_Style;
1151 }
1152
Chris Craik2af46352012-11-26 18:30:17 -08001153 virtual const char* name() { return "DrawRect"; }
1154};
1155
Chris Craik5d116762013-02-19 17:49:31 -08001156class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001157public:
1158 DrawRectsOp(const float* rects, int count, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001159 : DrawBoundedOp(rects, count, paint),
1160 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001161
Chris Craik527a3aa2013-03-04 10:19:31 -08001162 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001163 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1164 }
1165
Chris Craikc5493fb2013-06-19 16:58:58 -07001166 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001167 OP_LOG("Draw Rects count %d", mCount);
1168 }
1169
1170 virtual const char* name() { return "DrawRects"; }
1171
Chris Craik28ce94a2013-05-31 11:38:03 -07001172 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1173 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001174 }
1175
Chris Craik2af46352012-11-26 18:30:17 -08001176private:
1177 const float* mRects;
1178 int mCount;
1179};
1180
1181class DrawRoundRectOp : public DrawStrokableOp {
1182public:
1183 DrawRoundRectOp(float left, float top, float right, float bottom,
1184 float rx, float ry, SkPaint* paint)
1185 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1186
Chris Craik527a3aa2013-03-04 10:19:31 -08001187 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001188 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1189 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1190 }
1191
Chris Craikc5493fb2013-06-19 16:58:58 -07001192 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001193 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
1194 }
1195
1196 virtual const char* name() { return "DrawRoundRect"; }
1197
1198private:
1199 float mRx;
1200 float mRy;
1201};
1202
1203class DrawCircleOp : public DrawStrokableOp {
1204public:
1205 DrawCircleOp(float x, float y, float radius, SkPaint* paint)
1206 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1207 mX(x), mY(y), mRadius(radius) {}
1208
Chris Craik527a3aa2013-03-04 10:19:31 -08001209 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001210 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1211 }
1212
Chris Craikc5493fb2013-06-19 16:58:58 -07001213 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001214 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1215 }
1216
1217 virtual const char* name() { return "DrawCircle"; }
1218
1219private:
1220 float mX;
1221 float mY;
1222 float mRadius;
1223};
1224
1225class DrawOvalOp : public DrawStrokableOp {
1226public:
1227 DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
1228 : DrawStrokableOp(left, top, right, bottom, paint) {}
1229
Chris Craik527a3aa2013-03-04 10:19:31 -08001230 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001231 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1232 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1233 }
1234
Chris Craikc5493fb2013-06-19 16:58:58 -07001235 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001236 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
1237 }
1238
1239 virtual const char* name() { return "DrawOval"; }
1240};
1241
1242class DrawArcOp : public DrawStrokableOp {
1243public:
1244 DrawArcOp(float left, float top, float right, float bottom,
1245 float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
1246 : DrawStrokableOp(left, top, right, bottom, paint),
1247 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1248
Chris Craik527a3aa2013-03-04 10:19:31 -08001249 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001250 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1251 mLocalBounds.right, mLocalBounds.bottom,
1252 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1253 }
1254
Chris Craikc5493fb2013-06-19 16:58:58 -07001255 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001256 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
1257 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1258 }
1259
1260 virtual const char* name() { return "DrawArc"; }
1261
1262private:
1263 float mStartAngle;
1264 float mSweepAngle;
1265 bool mUseCenter;
1266};
1267
1268class DrawPathOp : public DrawBoundedOp {
1269public:
1270 DrawPathOp(SkPath* path, SkPaint* paint)
1271 : DrawBoundedOp(paint), mPath(path) {
1272 float left, top, offset;
1273 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001274 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001275 left -= offset;
1276 top -= offset;
1277 mLocalBounds.set(left, top, left + width, top + height);
1278 }
1279
Chris Craik527a3aa2013-03-04 10:19:31 -08001280 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001281 return renderer.drawPath(mPath, getPaint(renderer));
1282 }
1283
Chris Craik28ce94a2013-05-31 11:38:03 -07001284 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Romain Guyca89e2a2013-03-08 17:44:20 -08001285 SkPaint* paint = getPaint(renderer);
1286 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001287
Chris Craik28ce94a2013-05-31 11:38:03 -07001288 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001289 }
1290
Chris Craikc5493fb2013-06-19 16:58:58 -07001291 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001292 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1293 }
1294
1295 virtual const char* name() { return "DrawPath"; }
1296
1297private:
1298 SkPath* mPath;
1299};
1300
Chris Craikc3566d02013-02-04 16:16:33 -08001301class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001302public:
1303 DrawLinesOp(float* points, int count, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001304 : DrawBoundedOp(points, count, paint),
1305 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001306 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001307 }
1308
Chris Craik527a3aa2013-03-04 10:19:31 -08001309 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001310 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1311 }
1312
Chris Craikc5493fb2013-06-19 16:58:58 -07001313 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001314 OP_LOG("Draw Lines count %d", mCount);
1315 }
1316
1317 virtual const char* name() { return "DrawLines"; }
1318
Chris Craik28ce94a2013-05-31 11:38:03 -07001319 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1320 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001321 DeferredDisplayList::kOpBatch_AlphaVertices :
1322 DeferredDisplayList::kOpBatch_Vertices;
1323 }
1324
Chris Craik2af46352012-11-26 18:30:17 -08001325protected:
1326 float* mPoints;
1327 int mCount;
1328};
1329
1330class DrawPointsOp : public DrawLinesOp {
1331public:
1332 DrawPointsOp(float* points, int count, SkPaint* paint)
1333 : DrawLinesOp(points, count, paint) {}
1334
Chris Craik527a3aa2013-03-04 10:19:31 -08001335 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001336 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1337 }
1338
Chris Craikc5493fb2013-06-19 16:58:58 -07001339 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001340 OP_LOG("Draw Points count %d", mCount);
1341 }
1342
1343 virtual const char* name() { return "DrawPoints"; }
1344};
1345
1346class DrawSomeTextOp : public DrawOp {
1347public:
1348 DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
1349 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1350
Chris Craikc5493fb2013-06-19 16:58:58 -07001351 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001352 OP_LOG("Draw some text, %d bytes", mBytesCount);
1353 }
Chris Craikc3566d02013-02-04 16:16:33 -08001354
Chris Craik28ce94a2013-05-31 11:38:03 -07001355 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Romain Guy0f667532013-03-01 14:31:04 -08001356 SkPaint* paint = getPaint(renderer);
1357 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1358 fontRenderer.precache(paint, mText, mCount, mat4::identity());
Romain Guy0f667532013-03-01 14:31:04 -08001359
Chris Craik28ce94a2013-05-31 11:38:03 -07001360 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craikc3566d02013-02-04 16:16:33 -08001361 DeferredDisplayList::kOpBatch_Text :
1362 DeferredDisplayList::kOpBatch_ColorText;
1363 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001364
Chris Craik2af46352012-11-26 18:30:17 -08001365protected:
1366 const char* mText;
1367 int mBytesCount;
1368 int mCount;
1369};
1370
1371class DrawTextOnPathOp : public DrawSomeTextOp {
1372public:
1373 DrawTextOnPathOp(const char* text, int bytesCount, int count,
1374 SkPath* path, float hOffset, float vOffset, SkPaint* paint)
1375 : DrawSomeTextOp(text, bytesCount, count, paint),
1376 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1377 /* TODO: inherit from DrawBounded and init mLocalBounds */
1378 }
1379
Chris Craik527a3aa2013-03-04 10:19:31 -08001380 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001381 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1382 mHOffset, mVOffset, getPaint(renderer));
1383 }
1384
1385 virtual const char* name() { return "DrawTextOnPath"; }
1386
1387private:
1388 SkPath* mPath;
1389 float mHOffset;
1390 float mVOffset;
1391};
1392
1393class DrawPosTextOp : public DrawSomeTextOp {
1394public:
1395 DrawPosTextOp(const char* text, int bytesCount, int count,
1396 const float* positions, SkPaint* paint)
1397 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1398 /* TODO: inherit from DrawBounded and init mLocalBounds */
1399 }
1400
Chris Craik527a3aa2013-03-04 10:19:31 -08001401 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001402 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1403 }
1404
1405 virtual const char* name() { return "DrawPosText"; }
1406
1407private:
1408 const float* mPositions;
1409};
1410
1411class DrawTextOp : public DrawBoundedOp {
1412public:
1413 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craik41541822013-05-03 16:35:54 -07001414 const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds)
1415 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1416 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Romain Guybd3055f2013-03-13 16:14:47 -07001417 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
Chris Craik2af46352012-11-26 18:30:17 -08001418 }
1419
Chris Craik28ce94a2013-05-31 11:38:03 -07001420 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Romain Guy0f667532013-03-01 14:31:04 -08001421 SkPaint* paint = getPaint(renderer);
1422 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Romain Guybd3055f2013-03-13 16:14:47 -07001423 const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1424 if (mPrecacheTransform != transform) {
1425 fontRenderer.precache(paint, mText, mCount, transform);
1426 mPrecacheTransform = transform;
1427 }
Chris Craik28ce94a2013-05-31 11:38:03 -07001428 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001429 DeferredDisplayList::kOpBatch_Text :
1430 DeferredDisplayList::kOpBatch_ColorText;
1431
Chris Craik28ce94a2013-05-31 11:38:03 -07001432 deferInfo.mergeId = (mergeid_t)mPaint->getColor();
Chris Craik527a3aa2013-03-04 10:19:31 -08001433
1434 // don't merge decorated text - the decorations won't draw in order
1435 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
1436 SkPaint::kStrikeThruText_Flag));
Chris Craik28ce94a2013-05-31 11:38:03 -07001437 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations &&
1438 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001439 }
1440
Chris Craik527a3aa2013-03-04 10:19:31 -08001441 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001442 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Chris Craik41541822013-05-03 16:35:54 -07001443 mPositions, getPaint(renderer), mTotalAdvance, mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001444 }
1445
Chris Craik527a3aa2013-03-04 10:19:31 -08001446 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
1447 const Vector<DrawOp*>& ops, const Rect& bounds) {
1448 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001449 for (unsigned int i = 0; i < ops.size(); i++) {
1450 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
1451 renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip
1452
1453 DrawTextOp& op = *((DrawTextOp*)ops[i]);
1454 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001455 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1456 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001457 }
1458 return status;
1459 }
1460
Chris Craikc5493fb2013-06-19 16:58:58 -07001461 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001462 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1463 }
1464
1465 virtual const char* name() { return "DrawText"; }
1466
1467private:
1468 const char* mText;
1469 int mBytesCount;
1470 int mCount;
1471 float mX;
1472 float mY;
1473 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001474 float mTotalAdvance;
Romain Guybd3055f2013-03-13 16:14:47 -07001475 mat4 mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001476};
1477
1478///////////////////////////////////////////////////////////////////////////////
1479// SPECIAL DRAW OPERATIONS
1480///////////////////////////////////////////////////////////////////////////////
1481
1482class DrawFunctorOp : public DrawOp {
1483public:
1484 DrawFunctorOp(Functor* functor)
1485 : DrawOp(0), mFunctor(functor) {}
1486
Chris Craik527a3aa2013-03-04 10:19:31 -08001487 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001488 renderer.startMark("GL functor");
1489 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1490 renderer.endMark();
1491 return ret;
1492 }
1493
Chris Craikc5493fb2013-06-19 16:58:58 -07001494 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001495 OP_LOG("Draw Functor %p", mFunctor);
1496 }
1497
1498 virtual const char* name() { return "DrawFunctor"; }
1499
1500private:
1501 Functor* mFunctor;
1502};
1503
Chris Craik5d116762013-02-19 17:49:31 -08001504class DrawDisplayListOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001505public:
1506 DrawDisplayListOp(DisplayList* displayList, int flags)
Chris Craik5d116762013-02-19 17:49:31 -08001507 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
1508 mDisplayList(displayList), mFlags(flags) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001509
Chet Haasedd671592013-04-19 14:54:34 -07001510 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1511 bool useQuickReject) {
Chris Craikc3566d02013-02-04 16:16:33 -08001512 if (mDisplayList && mDisplayList->isRenderable()) {
Chris Craikff785832013-03-08 13:12:16 -08001513 mDisplayList->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001514 }
Chris Craikc3566d02013-02-04 16:16:33 -08001515 }
Chet Haasedd671592013-04-19 14:54:34 -07001516 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1517 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -08001518 if (mDisplayList && mDisplayList->isRenderable()) {
1519 mDisplayList->replay(replayStruct, level + 1);
1520 }
1521 }
Chris Craik2af46352012-11-26 18:30:17 -08001522
Chris Craika08f95c2013-03-15 17:24:33 -07001523 // NOT USED since replay() is overridden
Chris Craik527a3aa2013-03-04 10:19:31 -08001524 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001525 return DrawGlInfo::kStatusDone;
1526 }
Chris Craikff785832013-03-08 13:12:16 -08001527
Chris Craikc5493fb2013-06-19 16:58:58 -07001528 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001529 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
Chris Craikff785832013-03-08 13:12:16 -08001530 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
Chris Craik2af46352012-11-26 18:30:17 -08001531 mDisplayList->output(level + 1);
1532 }
1533 }
1534
1535 virtual const char* name() { return "DrawDisplayList"; }
1536
1537private:
1538 DisplayList* mDisplayList;
1539 int mFlags;
1540};
1541
1542class DrawLayerOp : public DrawOp {
1543public:
Chris Craika08f95c2013-03-15 17:24:33 -07001544 DrawLayerOp(Layer* layer, float x, float y)
1545 : DrawOp(0), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001546
Chris Craik527a3aa2013-03-04 10:19:31 -08001547 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001548 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001549 }
1550
Chris Craikc5493fb2013-06-19 16:58:58 -07001551 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001552 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1553 }
1554
1555 virtual const char* name() { return "DrawLayer"; }
1556
1557private:
1558 Layer* mLayer;
1559 float mX;
1560 float mY;
1561};
1562
1563}; // namespace uirenderer
1564}; // namespace android
1565
1566#endif // ANDROID_HWUI_DISPLAY_OPERATION_H