blob: 6c6eabbf903e16036cc422bfb07f292aa99c5789 [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
80 virtual void output(int level, uint32_t logFlags = 0) = 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 Craikff785832013-03-08 13:12:16 -0800281 virtual void output(int level, uint32_t logFlags) {
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
315 virtual void output(int level, uint32_t logFlags) {
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 Craikff785832013-03-08 13:12:16 -0800354 virtual void output(int level, uint32_t logFlags) {
355 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 Craikff785832013-03-08 13:12:16 -0800375 bool isSaveLayerAlpha() { 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 Craikff785832013-03-08 13:12:16 -0800391 virtual void output(int level, uint32_t logFlags) {
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 Craikff785832013-03-08 13:12:16 -0800411 virtual void output(int level, uint32_t logFlags) {
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 Craikff785832013-03-08 13:12:16 -0800430 virtual void output(int level, uint32_t logFlags) {
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 Craikff785832013-03-08 13:12:16 -0800450 virtual void output(int level, uint32_t logFlags) {
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 Craikff785832013-03-08 13:12:16 -0800470 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800471 OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
472 }
473
474 virtual const char* name() { return "SetMatrix"; }
475
476private:
477 SkMatrix* mMatrix;
478};
479
480class ConcatMatrixOp : public StateOp {
481public:
482 ConcatMatrixOp(SkMatrix* matrix)
483 : mMatrix(matrix) {}
484
Chris Craik7273daa2013-03-28 11:25:24 -0700485 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800486 renderer.concatMatrix(mMatrix);
487 }
488
Chris Craikff785832013-03-08 13:12:16 -0800489 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800490 OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
491 }
492
493 virtual const char* name() { return "ConcatMatrix"; }
494
495private:
496 SkMatrix* mMatrix;
497};
498
Chris Craikff785832013-03-08 13:12:16 -0800499class ClipOp : public StateOp {
500public:
501 ClipOp(SkRegion::Op op) : mOp(op) {}
502
Chet Haasedd671592013-04-19 14:54:34 -0700503 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
504 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800505 // NOTE: must defer op BEFORE applying state, since it may read clip
506 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
507
508 // TODO: Can we avoid applying complex clips at defer time?
509 applyState(deferStruct.mRenderer, saveCount);
510 }
511
512 bool canCauseComplexClip() {
513 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
514 }
515
516protected:
517 ClipOp() {}
518 virtual bool isRect() { return false; }
519
520 SkRegion::Op mOp;
521};
522
523class ClipRectOp : public ClipOp {
524 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800525public:
526 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800527 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800528
Chris Craik7273daa2013-03-28 11:25:24 -0700529 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800530 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
531 }
532
Chris Craikff785832013-03-08 13:12:16 -0800533 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800534 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
535 }
536
537 virtual const char* name() { return "ClipRect"; }
538
Chris Craikff785832013-03-08 13:12:16 -0800539protected:
540 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800541
Chris Craik2af46352012-11-26 18:30:17 -0800542private:
Chris Craikff785832013-03-08 13:12:16 -0800543 ClipRectOp() {}
544 DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
545 mOp = op;
546 mArea.set(left, top, right, bottom);
547 return this;
Chris Craikb98a0162013-02-21 11:30:22 -0800548 }
Chris Craikff785832013-03-08 13:12:16 -0800549
Chris Craik2af46352012-11-26 18:30:17 -0800550 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800551};
552
Chris Craikff785832013-03-08 13:12:16 -0800553class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800554public:
555 ClipPathOp(SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800556 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800557
Chris Craik7273daa2013-03-28 11:25:24 -0700558 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800559 renderer.clipPath(mPath, mOp);
560 }
561
Chris Craikff785832013-03-08 13:12:16 -0800562 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800563 SkRect bounds = mPath->getBounds();
564 OP_LOG("ClipPath bounds " RECT_STRING,
565 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
566 }
567
568 virtual const char* name() { return "ClipPath"; }
569
570private:
571 SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800572};
573
Chris Craikff785832013-03-08 13:12:16 -0800574class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800575public:
576 ClipRegionOp(SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800577 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800578
Chris Craik7273daa2013-03-28 11:25:24 -0700579 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800580 renderer.clipRegion(mRegion, mOp);
581 }
582
Chris Craikff785832013-03-08 13:12:16 -0800583 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800584 SkIRect bounds = mRegion->getBounds();
585 OP_LOG("ClipRegion bounds %d %d %d %d",
586 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
587 }
588
589 virtual const char* name() { return "ClipRegion"; }
590
591private:
592 SkRegion* mRegion;
593 SkRegion::Op mOp;
594};
595
596class ResetShaderOp : public StateOp {
597public:
Chris Craik7273daa2013-03-28 11:25:24 -0700598 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800599 renderer.resetShader();
600 }
601
Chris Craikff785832013-03-08 13:12:16 -0800602 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800603 OP_LOGS("ResetShader");
604 }
605
606 virtual const char* name() { return "ResetShader"; }
607};
608
609class SetupShaderOp : public StateOp {
610public:
611 SetupShaderOp(SkiaShader* shader)
612 : mShader(shader) {}
Chris Craik7273daa2013-03-28 11:25:24 -0700613 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800614 renderer.setupShader(mShader);
615 }
616
Chris Craikff785832013-03-08 13:12:16 -0800617 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800618 OP_LOG("SetupShader, shader %p", mShader);
619 }
620
621 virtual const char* name() { return "SetupShader"; }
622
623private:
624 SkiaShader* mShader;
625};
626
627class ResetColorFilterOp : public StateOp {
628public:
Chris Craik7273daa2013-03-28 11:25:24 -0700629 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800630 renderer.resetColorFilter();
631 }
632
Chris Craikff785832013-03-08 13:12:16 -0800633 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800634 OP_LOGS("ResetColorFilter");
635 }
636
637 virtual const char* name() { return "ResetColorFilter"; }
638};
639
640class SetupColorFilterOp : public StateOp {
641public:
642 SetupColorFilterOp(SkiaColorFilter* colorFilter)
643 : mColorFilter(colorFilter) {}
644
Chris Craik7273daa2013-03-28 11:25:24 -0700645 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800646 renderer.setupColorFilter(mColorFilter);
647 }
648
Chris Craikff785832013-03-08 13:12:16 -0800649 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800650 OP_LOG("SetupColorFilter, filter %p", mColorFilter);
651 }
652
653 virtual const char* name() { return "SetupColorFilter"; }
654
655private:
656 SkiaColorFilter* mColorFilter;
657};
658
659class ResetShadowOp : public StateOp {
660public:
Chris Craik7273daa2013-03-28 11:25:24 -0700661 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800662 renderer.resetShadow();
663 }
664
Chris Craikff785832013-03-08 13:12:16 -0800665 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800666 OP_LOGS("ResetShadow");
667 }
668
669 virtual const char* name() { return "ResetShadow"; }
670};
671
672class SetupShadowOp : public StateOp {
673public:
674 SetupShadowOp(float radius, float dx, float dy, int color)
675 : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
676
Chris Craik7273daa2013-03-28 11:25:24 -0700677 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800678 renderer.setupShadow(mRadius, mDx, mDy, mColor);
679 }
680
Chris Craikff785832013-03-08 13:12:16 -0800681 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800682 OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
683 }
684
685 virtual const char* name() { return "SetupShadow"; }
686
687private:
688 float mRadius;
689 float mDx;
690 float mDy;
691 int mColor;
692};
693
694class ResetPaintFilterOp : public StateOp {
695public:
Chris Craik7273daa2013-03-28 11:25:24 -0700696 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800697 renderer.resetPaintFilter();
698 }
699
Chris Craikff785832013-03-08 13:12:16 -0800700 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800701 OP_LOGS("ResetPaintFilter");
702 }
703
704 virtual const char* name() { return "ResetPaintFilter"; }
705};
706
707class SetupPaintFilterOp : public StateOp {
708public:
709 SetupPaintFilterOp(int clearBits, int setBits)
710 : mClearBits(clearBits), mSetBits(setBits) {}
711
Chris Craik7273daa2013-03-28 11:25:24 -0700712 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800713 renderer.setupPaintFilter(mClearBits, mSetBits);
714 }
715
Chris Craikff785832013-03-08 13:12:16 -0800716 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800717 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
718 }
719
720 virtual const char* name() { return "SetupPaintFilter"; }
721
722private:
723 int mClearBits;
724 int mSetBits;
725};
726
Chris Craik2af46352012-11-26 18:30:17 -0800727///////////////////////////////////////////////////////////////////////////////
728// DRAW OPERATIONS - these are operations that can draw to the canvas's device
729///////////////////////////////////////////////////////////////////////////////
730
731class DrawBitmapOp : public DrawBoundedOp {
732public:
733 DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
Romain Guy3b748a42013-04-17 18:54:38 -0700734 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
735 mBitmap(bitmap), mAtlasEntry(NULL) {
736 }
737
738 DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint,
739 const AssetAtlas::Entry* entry)
740 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
741 mBitmap(bitmap), mAtlasEntry(entry) {
742 if (entry) mUvMapper = entry->uvMapper;
743 }
Chris Craik2af46352012-11-26 18:30:17 -0800744
Chris Craik527a3aa2013-03-04 10:19:31 -0800745 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -0700746 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
747 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800748 }
749
Chris Craik527a3aa2013-03-04 10:19:31 -0800750#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
751 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
752 texCoordsRect.xDim, texCoordsRect.yDim)
753
Romain Guy03c00b52013-06-20 18:30:28 -0700754 /**
755 * This multi-draw operation builds a mesh on the stack by generating a quad
756 * for each bitmap in the batch. This method is also responsible for dirtying
757 * the current layer, if any.
758 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800759 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
760 const Vector<DrawOp*>& ops, const Rect& bounds) {
761 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -0800762 TextureVertex vertices[6 * ops.size()];
763 TextureVertex* vertex = &vertices[0];
764
Romain Guy03c00b52013-06-20 18:30:28 -0700765 const bool hasLayer = renderer.hasLayer();
Romain Guy2db5e992013-05-21 15:29:59 -0700766 bool transformed = false;
767
Romain Guy3b748a42013-04-17 18:54:38 -0700768 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
769 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800770 for (unsigned int i = 0; i < ops.size(); i++) {
771 const Rect& opBounds = ops[i]->state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700772 // When we reach multiDraw(), the matrix can be either
773 // pureTranslate or simple (translate and/or scale).
774 // If the matrix is not pureTranslate, then we have a scale
775 if (!ops[i]->state.mMatrix.isPureTranslate()) transformed = true;
Romain Guy3b748a42013-04-17 18:54:38 -0700776
777 Rect texCoords(0, 0, 1, 1);
778 ((DrawBitmapOp*) ops[i])->mUvMapper.map(texCoords);
779
Chris Craik527a3aa2013-03-04 10:19:31 -0800780 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
781 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
782 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
783
784 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
785 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
786 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700787
788 if (hasLayer) {
789 const Rect& dirty = ops[i]->state.mBounds;
790 renderer.dirtyLayer(dirty.left, dirty.top, dirty.right, dirty.bottom);
791 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800792 }
793
Romain Guy2db5e992013-05-21 15:29:59 -0700794 return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0],
795 transformed, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800796 }
797
Chris Craikff785832013-03-08 13:12:16 -0800798 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800799 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
800 }
801
802 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800803
Chris Craik28ce94a2013-05-31 11:38:03 -0700804 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
805 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
806 deferInfo.mergeId = mAtlasEntry ? (mergeid_t) &mAtlasEntry->atlas : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700807
Chris Craik28ce94a2013-05-31 11:38:03 -0700808 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
809 // MergingDrawBatch::canMergeWith()
810 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
811 deferInfo.mergeable = state.mMatrix.isSimple() && !state.mClipSideFlags &&
812 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
813 (mBitmap->getConfig() != SkBitmap::kA8_Config);
Chris Craikc3566d02013-02-04 16:16:33 -0800814 }
Chris Craik2af46352012-11-26 18:30:17 -0800815
Chris Craik527a3aa2013-03-04 10:19:31 -0800816 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800817protected:
818 SkBitmap* mBitmap;
Romain Guy3b748a42013-04-17 18:54:38 -0700819 const AssetAtlas::Entry* mAtlasEntry;
820 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800821};
822
823class DrawBitmapMatrixOp : public DrawBoundedOp {
824public:
825 DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
826 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
827 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
828 const mat4 transform(*matrix);
829 transform.mapRect(mLocalBounds);
830 }
831
Chris Craik527a3aa2013-03-04 10:19:31 -0800832 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800833 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
834 }
835
Chris Craikff785832013-03-08 13:12:16 -0800836 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800837 OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
838 }
839
Chris Craik527a3aa2013-03-04 10:19:31 -0800840 virtual const char* name() { return "DrawBitmapMatrix"; }
841
Chris Craik28ce94a2013-05-31 11:38:03 -0700842 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
843 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800844 }
Chris Craik2af46352012-11-26 18:30:17 -0800845
846private:
847 SkBitmap* mBitmap;
848 SkMatrix* mMatrix;
849};
850
851class DrawBitmapRectOp : public DrawBoundedOp {
852public:
853 DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
854 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
855 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
856 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
857
Chris Craik527a3aa2013-03-04 10:19:31 -0800858 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800859 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
860 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
861 getPaint(renderer));
862 }
863
Chris Craikff785832013-03-08 13:12:16 -0800864 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800865 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
866 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
867 }
868
869 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800870
Chris Craik28ce94a2013-05-31 11:38:03 -0700871 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
872 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800873 }
Chris Craik2af46352012-11-26 18:30:17 -0800874
875private:
876 SkBitmap* mBitmap;
877 Rect mSrc;
878};
879
880class DrawBitmapDataOp : public DrawBitmapOp {
881public:
882 DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
883 : DrawBitmapOp(bitmap, left, top, paint) {}
884
Chris Craik527a3aa2013-03-04 10:19:31 -0800885 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800886 return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
887 mLocalBounds.top, getPaint(renderer));
888 }
889
Chris Craikff785832013-03-08 13:12:16 -0800890 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800891 OP_LOG("Draw bitmap %p", mBitmap);
892 }
893
894 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800895
Chris Craik28ce94a2013-05-31 11:38:03 -0700896 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
897 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800898 }
Chris Craik2af46352012-11-26 18:30:17 -0800899};
900
Chris Craik5d116762013-02-19 17:49:31 -0800901class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800902public:
903 DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
904 float* vertices, int* colors, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800905 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
906 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800907 mVertices(vertices), mColors(colors) {}
908
Chris Craik527a3aa2013-03-04 10:19:31 -0800909 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800910 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
911 mVertices, mColors, getPaint(renderer));
912 }
913
Chris Craikff785832013-03-08 13:12:16 -0800914 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -0800915 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
916 }
917
918 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800919
Chris Craik28ce94a2013-05-31 11:38:03 -0700920 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
921 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800922 }
Chris Craik2af46352012-11-26 18:30:17 -0800923
924private:
925 SkBitmap* mBitmap;
926 int mMeshWidth;
927 int mMeshHeight;
928 float* mVertices;
929 int* mColors;
930};
931
932class DrawPatchOp : public DrawBoundedOp {
933public:
Romain Guy3b748a42013-04-17 18:54:38 -0700934 DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch,
Romain Guy03c00b52013-06-20 18:30:28 -0700935 float left, float top, float right, float bottom, SkPaint* paint)
936 : DrawBoundedOp(left, top, right, bottom, paint),
937 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL) {
Romain Guy3b748a42013-04-17 18:54:38 -0700938 mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap);
939 };
Chris Craik2af46352012-11-26 18:30:17 -0800940
Romain Guy03c00b52013-06-20 18:30:28 -0700941 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700942 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
943 PatchCache& cache = renderer.getCaches().patchCache;
944 mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700945 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700946 mGenerationId = cache.getGenerationId();
947 }
Romain Guy03c00b52013-06-20 18:30:28 -0700948 return mMesh;
949 }
950
951 /**
952 * This multi-draw operation builds an indexed mesh on the stack by copying
953 * and transforming the vertices of each 9-patch in the batch. This method
954 * is also responsible for dirtying the current layer, if any.
955 */
956 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
957 const Vector<DrawOp*>& ops, const Rect& bounds) {
958 renderer.restoreDisplayState(state, true);
959
960 // Batches will usually contain a small number of items so it's
961 // worth performing a first iteration to count the exact number
962 // of vertices we need in the new mesh
963 uint32_t totalVertices = 0;
964 for (unsigned int i = 0; i < ops.size(); i++) {
965 totalVertices += ((DrawPatchOp*) ops[i])->getMesh(renderer)->verticesCount;
966 }
967
968 const bool hasLayer = renderer.hasLayer();
969
970 uint32_t indexCount = 0;
971
972 TextureVertex vertices[totalVertices];
973 TextureVertex* vertex = &vertices[0];
974
975 // Create a mesh that contains the transformed vertices for all the
976 // 9-patch objects that are part of the batch. Note that onDefer()
977 // enforces ops drawn by this function to have a pure translate or
978 // identity matrix
979 for (unsigned int i = 0; i < ops.size(); i++) {
980 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i];
981 const Patch* opMesh = patchOp->getMesh(renderer);
982 uint32_t vertexCount = opMesh->verticesCount;
983 if (vertexCount == 0) continue;
984
985 // We use the bounds to know where to translate our vertices
986 // Using patchOp->state.mBounds wouldn't work because these
987 // bounds are clipped
988 const float tx = (int) floorf(patchOp->state.mMatrix.getTranslateX() +
989 patchOp->mLocalBounds.left + 0.5f);
990 const float ty = (int) floorf(patchOp->state.mMatrix.getTranslateY() +
991 patchOp->mLocalBounds.top + 0.5f);
992
993 // Copy & transform all the vertices for the current operation
994 TextureVertex* opVertices = opMesh->vertices;
995 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
996 TextureVertex::set(vertex++,
997 opVertices->position[0] + tx, opVertices->position[1] + ty,
998 opVertices->texture[0], opVertices->texture[1]);
999 }
1000
1001 // Dirty the current layer if possible. When the 9-patch does not
1002 // contain empty quads we can take a shortcut and simply set the
1003 // dirty rect to the object's bounds.
1004 if (hasLayer) {
1005 if (!opMesh->hasEmptyQuads) {
1006 renderer.dirtyLayer(tx, ty,
1007 tx + patchOp->mLocalBounds.getWidth(),
1008 ty + patchOp->mLocalBounds.getHeight());
1009 } else {
1010 const size_t count = opMesh->quads.size();
1011 for (size_t i = 0; i < count; i++) {
1012 const Rect& quadBounds = opMesh->quads[i];
1013 const float x = tx + quadBounds.left;
1014 const float y = ty + quadBounds.top;
1015 renderer.dirtyLayer(x, y,
1016 x + quadBounds.getWidth(), y + quadBounds.getHeight());
1017 }
1018 }
1019 }
1020
1021 indexCount += opMesh->indexCount;
1022 }
1023
1024 return renderer.drawPatches(mBitmap, mEntry, &vertices[0], indexCount, getPaint(renderer));
1025 }
1026
1027 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -07001028 // We're not calling the public variant of drawPatch() here
1029 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy03c00b52013-06-20 18:30:28 -07001030 return renderer.drawPatch(mBitmap, getMesh(renderer), mEntry,
1031 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
1032 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -08001033 }
1034
Chris Craikff785832013-03-08 13:12:16 -08001035 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001036 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
1037 }
1038
1039 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -08001040
Chris Craik28ce94a2013-05-31 11:38:03 -07001041 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1042 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy5216c3b2013-06-14 16:31:37 -07001043 deferInfo.mergeId = mEntry ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -07001044 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
1045 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy5216c3b2013-06-14 16:31:37 -07001046 deferInfo.opaqueOverBounds = isOpaqueOverBounds() && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -08001047 }
Chris Craik2af46352012-11-26 18:30:17 -08001048
1049private:
1050 SkBitmap* mBitmap;
Romain Guy3b748a42013-04-17 18:54:38 -07001051 Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -07001052
Romain Guy4c2547f2013-06-11 16:19:24 -07001053 uint32_t mGenerationId;
1054 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -07001055
Romain Guy3b748a42013-04-17 18:54:38 -07001056 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -08001057};
1058
1059class DrawColorOp : public DrawOp {
1060public:
1061 DrawColorOp(int color, SkXfermode::Mode mode)
1062 : DrawOp(0), mColor(color), mMode(mode) {};
1063
Chris Craik527a3aa2013-03-04 10:19:31 -08001064 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001065 return renderer.drawColor(mColor, mMode);
1066 }
1067
Chris Craikff785832013-03-08 13:12:16 -08001068 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001069 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
1070 }
1071
1072 virtual const char* name() { return "DrawColor"; }
1073
1074private:
1075 int mColor;
1076 SkXfermode::Mode mMode;
1077};
1078
1079class DrawStrokableOp : public DrawBoundedOp {
1080public:
1081 DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
1082 : DrawBoundedOp(left, top, right, bottom, paint) {};
1083
1084 bool getLocalBounds(Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001085 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001086 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001087 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001088 }
1089 return true;
1090 }
Chris Craikc3566d02013-02-04 16:16:33 -08001091
Chris Craik28ce94a2013-05-31 11:38:03 -07001092 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Chris Craikc3566d02013-02-04 16:16:33 -08001093 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001094 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001095 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001096 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001097 DeferredDisplayList::kOpBatch_AlphaVertices :
1098 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001099 }
Chris Craikc3566d02013-02-04 16:16:33 -08001100 }
Chris Craik2af46352012-11-26 18:30:17 -08001101};
1102
1103class DrawRectOp : public DrawStrokableOp {
1104public:
1105 DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
1106 : DrawStrokableOp(left, top, right, bottom, paint) {}
1107
Chris Craik527a3aa2013-03-04 10:19:31 -08001108 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001109 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1110 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1111 }
1112
Chris Craikff785832013-03-08 13:12:16 -08001113 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001114 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
1115 }
1116
Chris Craik28ce94a2013-05-31 11:38:03 -07001117 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1118 DrawStrokableOp::onDefer(renderer, deferInfo);
1119 deferInfo.opaqueOverBounds = isOpaqueOverBounds() &&
1120 mPaint->getStyle() == SkPaint::kFill_Style;
1121 }
1122
Chris Craik2af46352012-11-26 18:30:17 -08001123 virtual const char* name() { return "DrawRect"; }
1124};
1125
Chris Craik5d116762013-02-19 17:49:31 -08001126class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001127public:
1128 DrawRectsOp(const float* rects, int count, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001129 : DrawBoundedOp(rects, count, paint),
1130 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001131
Chris Craik527a3aa2013-03-04 10:19:31 -08001132 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001133 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1134 }
1135
Chris Craikff785832013-03-08 13:12:16 -08001136 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001137 OP_LOG("Draw Rects count %d", mCount);
1138 }
1139
1140 virtual const char* name() { return "DrawRects"; }
1141
Chris Craik28ce94a2013-05-31 11:38:03 -07001142 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1143 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001144 }
1145
Chris Craik2af46352012-11-26 18:30:17 -08001146private:
1147 const float* mRects;
1148 int mCount;
1149};
1150
1151class DrawRoundRectOp : public DrawStrokableOp {
1152public:
1153 DrawRoundRectOp(float left, float top, float right, float bottom,
1154 float rx, float ry, SkPaint* paint)
1155 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1156
Chris Craik527a3aa2013-03-04 10:19:31 -08001157 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001158 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1159 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1160 }
1161
Chris Craikff785832013-03-08 13:12:16 -08001162 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001163 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
1164 }
1165
1166 virtual const char* name() { return "DrawRoundRect"; }
1167
1168private:
1169 float mRx;
1170 float mRy;
1171};
1172
1173class DrawCircleOp : public DrawStrokableOp {
1174public:
1175 DrawCircleOp(float x, float y, float radius, SkPaint* paint)
1176 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1177 mX(x), mY(y), mRadius(radius) {}
1178
Chris Craik527a3aa2013-03-04 10:19:31 -08001179 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001180 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1181 }
1182
Chris Craikff785832013-03-08 13:12:16 -08001183 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001184 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1185 }
1186
1187 virtual const char* name() { return "DrawCircle"; }
1188
1189private:
1190 float mX;
1191 float mY;
1192 float mRadius;
1193};
1194
1195class DrawOvalOp : public DrawStrokableOp {
1196public:
1197 DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
1198 : DrawStrokableOp(left, top, right, bottom, paint) {}
1199
Chris Craik527a3aa2013-03-04 10:19:31 -08001200 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001201 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1202 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1203 }
1204
Chris Craikff785832013-03-08 13:12:16 -08001205 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001206 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
1207 }
1208
1209 virtual const char* name() { return "DrawOval"; }
1210};
1211
1212class DrawArcOp : public DrawStrokableOp {
1213public:
1214 DrawArcOp(float left, float top, float right, float bottom,
1215 float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
1216 : DrawStrokableOp(left, top, right, bottom, paint),
1217 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1218
Chris Craik527a3aa2013-03-04 10:19:31 -08001219 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001220 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1221 mLocalBounds.right, mLocalBounds.bottom,
1222 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1223 }
1224
Chris Craikff785832013-03-08 13:12:16 -08001225 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001226 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
1227 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1228 }
1229
1230 virtual const char* name() { return "DrawArc"; }
1231
1232private:
1233 float mStartAngle;
1234 float mSweepAngle;
1235 bool mUseCenter;
1236};
1237
1238class DrawPathOp : public DrawBoundedOp {
1239public:
1240 DrawPathOp(SkPath* path, SkPaint* paint)
1241 : DrawBoundedOp(paint), mPath(path) {
1242 float left, top, offset;
1243 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001244 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001245 left -= offset;
1246 top -= offset;
1247 mLocalBounds.set(left, top, left + width, top + height);
1248 }
1249
Chris Craik527a3aa2013-03-04 10:19:31 -08001250 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001251 return renderer.drawPath(mPath, getPaint(renderer));
1252 }
1253
Chris Craik28ce94a2013-05-31 11:38:03 -07001254 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Romain Guyca89e2a2013-03-08 17:44:20 -08001255 SkPaint* paint = getPaint(renderer);
1256 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001257
Chris Craik28ce94a2013-05-31 11:38:03 -07001258 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001259 }
1260
Chris Craikff785832013-03-08 13:12:16 -08001261 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001262 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1263 }
1264
1265 virtual const char* name() { return "DrawPath"; }
1266
1267private:
1268 SkPath* mPath;
1269};
1270
Chris Craikc3566d02013-02-04 16:16:33 -08001271class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001272public:
1273 DrawLinesOp(float* points, int count, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001274 : DrawBoundedOp(points, count, paint),
1275 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001276 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001277 }
1278
Chris Craik527a3aa2013-03-04 10:19:31 -08001279 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001280 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1281 }
1282
Chris Craikff785832013-03-08 13:12:16 -08001283 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001284 OP_LOG("Draw Lines count %d", mCount);
1285 }
1286
1287 virtual const char* name() { return "DrawLines"; }
1288
Chris Craik28ce94a2013-05-31 11:38:03 -07001289 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
1290 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001291 DeferredDisplayList::kOpBatch_AlphaVertices :
1292 DeferredDisplayList::kOpBatch_Vertices;
1293 }
1294
Chris Craik2af46352012-11-26 18:30:17 -08001295protected:
1296 float* mPoints;
1297 int mCount;
1298};
1299
1300class DrawPointsOp : public DrawLinesOp {
1301public:
1302 DrawPointsOp(float* points, int count, SkPaint* paint)
1303 : DrawLinesOp(points, count, paint) {}
1304
Chris Craik527a3aa2013-03-04 10:19:31 -08001305 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001306 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1307 }
1308
Chris Craikff785832013-03-08 13:12:16 -08001309 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001310 OP_LOG("Draw Points count %d", mCount);
1311 }
1312
1313 virtual const char* name() { return "DrawPoints"; }
1314};
1315
1316class DrawSomeTextOp : public DrawOp {
1317public:
1318 DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
1319 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1320
Chris Craikff785832013-03-08 13:12:16 -08001321 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001322 OP_LOG("Draw some text, %d bytes", mBytesCount);
1323 }
Chris Craikc3566d02013-02-04 16:16:33 -08001324
Chris Craik28ce94a2013-05-31 11:38:03 -07001325 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Romain Guy0f667532013-03-01 14:31:04 -08001326 SkPaint* paint = getPaint(renderer);
1327 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1328 fontRenderer.precache(paint, mText, mCount, mat4::identity());
Romain Guy0f667532013-03-01 14:31:04 -08001329
Chris Craik28ce94a2013-05-31 11:38:03 -07001330 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craikc3566d02013-02-04 16:16:33 -08001331 DeferredDisplayList::kOpBatch_Text :
1332 DeferredDisplayList::kOpBatch_ColorText;
1333 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001334
Chris Craik2af46352012-11-26 18:30:17 -08001335protected:
1336 const char* mText;
1337 int mBytesCount;
1338 int mCount;
1339};
1340
1341class DrawTextOnPathOp : public DrawSomeTextOp {
1342public:
1343 DrawTextOnPathOp(const char* text, int bytesCount, int count,
1344 SkPath* path, float hOffset, float vOffset, SkPaint* paint)
1345 : DrawSomeTextOp(text, bytesCount, count, paint),
1346 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1347 /* TODO: inherit from DrawBounded and init mLocalBounds */
1348 }
1349
Chris Craik527a3aa2013-03-04 10:19:31 -08001350 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001351 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1352 mHOffset, mVOffset, getPaint(renderer));
1353 }
1354
1355 virtual const char* name() { return "DrawTextOnPath"; }
1356
1357private:
1358 SkPath* mPath;
1359 float mHOffset;
1360 float mVOffset;
1361};
1362
1363class DrawPosTextOp : public DrawSomeTextOp {
1364public:
1365 DrawPosTextOp(const char* text, int bytesCount, int count,
1366 const float* positions, SkPaint* paint)
1367 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1368 /* TODO: inherit from DrawBounded and init mLocalBounds */
1369 }
1370
Chris Craik527a3aa2013-03-04 10:19:31 -08001371 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001372 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1373 }
1374
1375 virtual const char* name() { return "DrawPosText"; }
1376
1377private:
1378 const float* mPositions;
1379};
1380
1381class DrawTextOp : public DrawBoundedOp {
1382public:
1383 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craik41541822013-05-03 16:35:54 -07001384 const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds)
1385 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1386 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Romain Guybd3055f2013-03-13 16:14:47 -07001387 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
Chris Craik2af46352012-11-26 18:30:17 -08001388 }
1389
Chris Craik28ce94a2013-05-31 11:38:03 -07001390 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {
Romain Guy0f667532013-03-01 14:31:04 -08001391 SkPaint* paint = getPaint(renderer);
1392 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Romain Guybd3055f2013-03-13 16:14:47 -07001393 const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1394 if (mPrecacheTransform != transform) {
1395 fontRenderer.precache(paint, mText, mCount, transform);
1396 mPrecacheTransform = transform;
1397 }
Chris Craik28ce94a2013-05-31 11:38:03 -07001398 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001399 DeferredDisplayList::kOpBatch_Text :
1400 DeferredDisplayList::kOpBatch_ColorText;
1401
Chris Craik28ce94a2013-05-31 11:38:03 -07001402 deferInfo.mergeId = (mergeid_t)mPaint->getColor();
Chris Craik527a3aa2013-03-04 10:19:31 -08001403
1404 // don't merge decorated text - the decorations won't draw in order
1405 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
1406 SkPaint::kStrikeThruText_Flag));
Chris Craik28ce94a2013-05-31 11:38:03 -07001407 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations &&
1408 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001409 }
1410
Chris Craik527a3aa2013-03-04 10:19:31 -08001411 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001412 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Chris Craik41541822013-05-03 16:35:54 -07001413 mPositions, getPaint(renderer), mTotalAdvance, mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001414 }
1415
Chris Craik527a3aa2013-03-04 10:19:31 -08001416 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
1417 const Vector<DrawOp*>& ops, const Rect& bounds) {
1418 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001419 for (unsigned int i = 0; i < ops.size(); i++) {
1420 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
1421 renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip
1422
1423 DrawTextOp& op = *((DrawTextOp*)ops[i]);
1424 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001425 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1426 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001427 }
1428 return status;
1429 }
1430
Chris Craikff785832013-03-08 13:12:16 -08001431 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001432 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1433 }
1434
1435 virtual const char* name() { return "DrawText"; }
1436
1437private:
1438 const char* mText;
1439 int mBytesCount;
1440 int mCount;
1441 float mX;
1442 float mY;
1443 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001444 float mTotalAdvance;
Romain Guybd3055f2013-03-13 16:14:47 -07001445 mat4 mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001446};
1447
1448///////////////////////////////////////////////////////////////////////////////
1449// SPECIAL DRAW OPERATIONS
1450///////////////////////////////////////////////////////////////////////////////
1451
1452class DrawFunctorOp : public DrawOp {
1453public:
1454 DrawFunctorOp(Functor* functor)
1455 : DrawOp(0), mFunctor(functor) {}
1456
Chris Craik527a3aa2013-03-04 10:19:31 -08001457 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001458 renderer.startMark("GL functor");
1459 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1460 renderer.endMark();
1461 return ret;
1462 }
1463
Chris Craikff785832013-03-08 13:12:16 -08001464 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001465 OP_LOG("Draw Functor %p", mFunctor);
1466 }
1467
1468 virtual const char* name() { return "DrawFunctor"; }
1469
1470private:
1471 Functor* mFunctor;
1472};
1473
Chris Craik5d116762013-02-19 17:49:31 -08001474class DrawDisplayListOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001475public:
1476 DrawDisplayListOp(DisplayList* displayList, int flags)
Chris Craik5d116762013-02-19 17:49:31 -08001477 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
1478 mDisplayList(displayList), mFlags(flags) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001479
Chet Haasedd671592013-04-19 14:54:34 -07001480 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1481 bool useQuickReject) {
Chris Craikc3566d02013-02-04 16:16:33 -08001482 if (mDisplayList && mDisplayList->isRenderable()) {
Chris Craikff785832013-03-08 13:12:16 -08001483 mDisplayList->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001484 }
Chris Craikc3566d02013-02-04 16:16:33 -08001485 }
Chet Haasedd671592013-04-19 14:54:34 -07001486 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1487 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -08001488 if (mDisplayList && mDisplayList->isRenderable()) {
1489 mDisplayList->replay(replayStruct, level + 1);
1490 }
1491 }
Chris Craik2af46352012-11-26 18:30:17 -08001492
Chris Craika08f95c2013-03-15 17:24:33 -07001493 // NOT USED since replay() is overridden
Chris Craik527a3aa2013-03-04 10:19:31 -08001494 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001495 return DrawGlInfo::kStatusDone;
1496 }
Chris Craikff785832013-03-08 13:12:16 -08001497
1498 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001499 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
Chris Craikff785832013-03-08 13:12:16 -08001500 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
Chris Craik2af46352012-11-26 18:30:17 -08001501 mDisplayList->output(level + 1);
1502 }
1503 }
1504
1505 virtual const char* name() { return "DrawDisplayList"; }
1506
1507private:
1508 DisplayList* mDisplayList;
1509 int mFlags;
1510};
1511
1512class DrawLayerOp : public DrawOp {
1513public:
Chris Craika08f95c2013-03-15 17:24:33 -07001514 DrawLayerOp(Layer* layer, float x, float y)
1515 : DrawOp(0), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001516
Chris Craik527a3aa2013-03-04 10:19:31 -08001517 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001518 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001519 }
1520
Chris Craikff785832013-03-08 13:12:16 -08001521 virtual void output(int level, uint32_t logFlags) {
Chris Craik2af46352012-11-26 18:30:17 -08001522 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1523 }
1524
1525 virtual const char* name() { return "DrawLayer"; }
1526
1527private:
1528 Layer* mLayer;
1529 float mX;
1530 float mY;
1531};
1532
1533}; // namespace uirenderer
1534}; // namespace android
1535
1536#endif // ANDROID_HWUI_DISPLAY_OPERATION_H