blob: 842e028427f37cc7f765efcae2b677a8ba46d5d0 [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;
85};
86
87class StateOp : public DisplayListOp {
88public:
89 StateOp() {};
90
91 virtual ~StateOp() {}
92
Chet Haasedd671592013-04-19 14:54:34 -070093 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
94 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -080095 // default behavior only affects immediate, deferrable state, issue directly to renderer
96 applyState(deferStruct.mRenderer, saveCount);
97 }
98
Chris Craikc3566d02013-02-04 16:16:33 -080099 /**
100 * State operations are applied directly to the renderer, but can cause the deferred drawing op
101 * list to flush
102 */
Chet Haasedd671592013-04-19 14:54:34 -0700103 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
104 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800105 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800106 }
107
Chris Craik7273daa2013-03-28 11:25:24 -0700108 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800109};
110
111class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800112friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800113public:
114 DrawOp(SkPaint* paint)
115 : mPaint(paint), mQuickRejected(false) {}
116
Chet Haasedd671592013-04-19 14:54:34 -0700117 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
118 bool useQuickReject) {
119 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800120 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800121 }
122
Chris Craikff785832013-03-08 13:12:16 -0800123 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800124 }
125
Chet Haasedd671592013-04-19 14:54:34 -0700126 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
127 bool useQuickReject) {
128 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800129 return;
130 }
131
Chris Craik527a3aa2013-03-04 10:19:31 -0800132 replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800133 }
134
Chris Craik527a3aa2013-03-04 10:19:31 -0800135 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800136
Chris Craik527a3aa2013-03-04 10:19:31 -0800137 /**
138 * Draw multiple instances of an operation, must be overidden for operations that merge
139 *
140 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
141 * and pure translation transformations. Other guarantees of similarity should be enforced by
142 * reducing which operations are tagged as mergeable.
143 */
144 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700145 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800146 status_t status = DrawGlInfo::kStatusDone;
147 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700148 renderer.restoreDisplayState(*(ops[i].state), true);
149 status |= ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800150 }
151 return status;
152 }
153
Chris Craik28ce94a2013-05-31 11:38:03 -0700154 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800155 * When this method is invoked the state field is initialized to have the
156 * final rendering state. We can thus use it to process data as it will be
157 * used at draw time.
158 *
159 * Additionally, this method allows subclasses to provide defer-time preferences for batching
160 * and merging.
161 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700162 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800163 */
Chris Craikc1c5f082013-09-11 16:23:37 -0700164 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
165 const DeferredDisplayState& state) {}
Romain Guy0f667532013-03-01 14:31:04 -0800166
Chris Craik5e49b302013-07-30 19:05:20 -0700167 /**
168 * Query the conservative, local bounds (unmapped) bounds of the op.
169 *
170 * returns true if bounds exist
171 */
Chris Craikc1c5f082013-09-11 16:23:37 -0700172 virtual bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
173 return false;
174 }
Chris Craik2af46352012-11-26 18:30:17 -0800175
176 // TODO: better refine localbounds usage
177 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
178 bool getQuickRejected() { return mQuickRejected; }
179
Chris Craikc1c5f082013-09-11 16:23:37 -0700180 inline int getPaintAlpha() const {
Chris Craik527a3aa2013-03-04 10:19:31 -0800181 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800182 }
183
Chris Craik527a3aa2013-03-04 10:19:31 -0800184 inline float strokeWidthOutset() {
Chris Craike7c69c62013-04-03 09:55:48 -0700185 float width = mPaint->getStrokeWidth();
186 if (width == 0) return 0.5f; // account for hairline
187 return width * 0.5f;
188 }
Chris Craikc3566d02013-02-04 16:16:33 -0800189
Chris Craik2af46352012-11-26 18:30:17 -0800190protected:
Chris Craika08f95c2013-03-15 17:24:33 -0700191 SkPaint* getPaint(OpenGLRenderer& renderer) {
192 return renderer.filterPaint(mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800193 }
194
Chris Craik28ce94a2013-05-31 11:38:03 -0700195 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
196 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700197 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700198 // ensure that local bounds cover mapped bounds
199 if (!state.mMatrix.isSimple()) return false;
200
201 // check state/paint for transparency
202 if (state.mDrawModifiers.mShader ||
203 state.mAlpha != 1.0f ||
204 (mPaint && mPaint->getAlpha() != 0xFF)) return false;
205
206 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
207 return (mode == SkXfermode::kSrcOver_Mode ||
208 mode == SkXfermode::kSrc_Mode);
209
210 }
211
Chris Craik2af46352012-11-26 18:30:17 -0800212 SkPaint* mPaint; // should be accessed via getPaint() when applying
213 bool mQuickRejected;
214};
215
216class DrawBoundedOp : public DrawOp {
217public:
218 DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
219 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
220
Chris Craik41541822013-05-03 16:35:54 -0700221 DrawBoundedOp(const Rect& localBounds, SkPaint* paint)
222 : DrawOp(paint), mLocalBounds(localBounds) {}
223
Chris Craik5d116762013-02-19 17:49:31 -0800224 // Calculates bounds as smallest rect encompassing all points
225 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
226 // subclass' constructor)
227 DrawBoundedOp(const float* points, int count, SkPaint* paint)
228 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
229 for (int i = 2; i < count; i += 2) {
230 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
231 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
232 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
233 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
234 }
235 }
236
237 // default empty constructor for bounds, to be overridden in child constructor body
Romain Guy9b5a1a22013-08-09 14:06:29 -0700238 DrawBoundedOp(SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800239
Chris Craikc1c5f082013-09-11 16:23:37 -0700240 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800241 localBounds.set(mLocalBounds);
Chris Craikc1c5f082013-09-11 16:23:37 -0700242 if (drawModifiers.mHasShadow) {
243 // TODO: inspect paint's looper directly
Romain Guy9b5a1a22013-08-09 14:06:29 -0700244 Rect shadow(mLocalBounds);
Chris Craikc1c5f082013-09-11 16:23:37 -0700245 shadow.translate(drawModifiers.mShadowDx, drawModifiers.mShadowDy);
246 shadow.outset(drawModifiers.mShadowRadius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700247 localBounds.unionWith(shadow);
248 }
Chris Craik2af46352012-11-26 18:30:17 -0800249 return true;
250 }
251
252protected:
253 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
254};
255
256///////////////////////////////////////////////////////////////////////////////
257// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
258// not directly draw or alter output
259///////////////////////////////////////////////////////////////////////////////
260
261class SaveOp : public StateOp {
Chris Craikff785832013-03-08 13:12:16 -0800262 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800263public:
264 SaveOp(int flags)
265 : mFlags(flags) {}
266
Chet Haasedd671592013-04-19 14:54:34 -0700267 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
268 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800269 int newSaveCount = deferStruct.mRenderer.save(mFlags);
270 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
271 }
272
Chris Craik7273daa2013-03-28 11:25:24 -0700273 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800274 renderer.save(mFlags);
275 }
276
Chris Craikc5493fb2013-06-19 16:58:58 -0700277 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800278 OP_LOG("Save flags %x", mFlags);
279 }
280
281 virtual const char* name() { return "Save"; }
282
Chris Craikff785832013-03-08 13:12:16 -0800283 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800284private:
Chris Craikff785832013-03-08 13:12:16 -0800285 SaveOp() {}
286 DisplayListOp* reinit(int flags) {
287 mFlags = flags;
288 return this;
289 }
290
Chris Craik2af46352012-11-26 18:30:17 -0800291 int mFlags;
292};
293
294class RestoreToCountOp : public StateOp {
Chris Craikff785832013-03-08 13:12:16 -0800295 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800296public:
297 RestoreToCountOp(int count)
298 : mCount(count) {}
299
Chet Haasedd671592013-04-19 14:54:34 -0700300 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
301 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700302 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
303 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800304 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800305 }
306
Chris Craik7273daa2013-03-28 11:25:24 -0700307 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800308 renderer.restoreToCount(saveCount + mCount);
309 }
310
Chris Craikc5493fb2013-06-19 16:58:58 -0700311 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800312 OP_LOG("Restore to count %d", mCount);
313 }
314
315 virtual const char* name() { return "RestoreToCount"; }
316
317private:
Chris Craikff785832013-03-08 13:12:16 -0800318 RestoreToCountOp() {}
319 DisplayListOp* reinit(int count) {
320 mCount = count;
321 return this;
322 }
323
Chris Craik2af46352012-11-26 18:30:17 -0800324 int mCount;
325};
326
327class SaveLayerOp : public StateOp {
Chris Craikff785832013-03-08 13:12:16 -0800328 friend class DisplayList; // give DisplayList private constructor/reinit access
Chris Craik2af46352012-11-26 18:30:17 -0800329public:
Chris Craikff785832013-03-08 13:12:16 -0800330 SaveLayerOp(float left, float top, float right, float bottom,
331 int alpha, SkXfermode::Mode mode, int flags)
332 : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
333
Chet Haasedd671592013-04-19 14:54:34 -0700334 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
335 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800336 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700337 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800338 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700339
340 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
341 // setup the snapshot for deferral, and re-issue the op at flush time
342 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
343 mAlpha, mMode, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800344 }
Chris Craik2af46352012-11-26 18:30:17 -0800345
Chris Craik7273daa2013-03-28 11:25:24 -0700346 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800347 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
Chris Craik2af46352012-11-26 18:30:17 -0800348 }
349
Chris Craikc5493fb2013-06-19 16:58:58 -0700350 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800351 OP_LOG("SaveLayer%s of area " RECT_STRING,
352 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800353 }
354
Chris Craikff785832013-03-08 13:12:16 -0800355 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
356
357 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800358
359private:
Chris Craikff785832013-03-08 13:12:16 -0800360 // Special case, reserved for direct DisplayList usage
361 SaveLayerOp() {}
362 DisplayListOp* reinit(float left, float top, float right, float bottom,
363 int alpha, SkXfermode::Mode mode, int flags) {
364 mArea.set(left, top, right, bottom);
365 mAlpha = alpha;
366 mMode = mode;
367 mFlags = flags;
368 return this;
Chris Craik2af46352012-11-26 18:30:17 -0800369 }
370
Chris Craikc5493fb2013-06-19 16:58:58 -0700371 bool isSaveLayerAlpha() const { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
Chris Craik2af46352012-11-26 18:30:17 -0800372 Rect mArea;
373 int mAlpha;
Chris Craikff785832013-03-08 13:12:16 -0800374 SkXfermode::Mode mMode;
Chris Craik2af46352012-11-26 18:30:17 -0800375 int mFlags;
376};
377
378class TranslateOp : public StateOp {
379public:
380 TranslateOp(float dx, float dy)
381 : mDx(dx), mDy(dy) {}
382
Chris Craik7273daa2013-03-28 11:25:24 -0700383 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800384 renderer.translate(mDx, mDy);
385 }
386
Chris Craikc5493fb2013-06-19 16:58:58 -0700387 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800388 OP_LOG("Translate by %f %f", mDx, mDy);
389 }
390
391 virtual const char* name() { return "Translate"; }
392
393private:
394 float mDx;
395 float mDy;
396};
397
398class RotateOp : public StateOp {
399public:
400 RotateOp(float degrees)
401 : mDegrees(degrees) {}
402
Chris Craik7273daa2013-03-28 11:25:24 -0700403 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800404 renderer.rotate(mDegrees);
405 }
406
Chris Craikc5493fb2013-06-19 16:58:58 -0700407 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800408 OP_LOG("Rotate by %f degrees", mDegrees);
409 }
410
411 virtual const char* name() { return "Rotate"; }
412
413private:
414 float mDegrees;
415};
416
417class ScaleOp : public StateOp {
418public:
419 ScaleOp(float sx, float sy)
420 : mSx(sx), mSy(sy) {}
421
Chris Craik7273daa2013-03-28 11:25:24 -0700422 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800423 renderer.scale(mSx, mSy);
424 }
425
Chris Craikc5493fb2013-06-19 16:58:58 -0700426 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800427 OP_LOG("Scale by %f %f", mSx, mSy);
428 }
429
430 virtual const char* name() { return "Scale"; }
431
432private:
433 float mSx;
434 float mSy;
435};
436
437class SkewOp : public StateOp {
438public:
439 SkewOp(float sx, float sy)
440 : mSx(sx), mSy(sy) {}
441
Chris Craik7273daa2013-03-28 11:25:24 -0700442 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800443 renderer.skew(mSx, mSy);
444 }
445
Chris Craikc5493fb2013-06-19 16:58:58 -0700446 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800447 OP_LOG("Skew by %f %f", mSx, mSy);
448 }
449
450 virtual const char* name() { return "Skew"; }
451
452private:
453 float mSx;
454 float mSy;
455};
456
457class SetMatrixOp : public StateOp {
458public:
459 SetMatrixOp(SkMatrix* matrix)
460 : mMatrix(matrix) {}
461
Chris Craik7273daa2013-03-28 11:25:24 -0700462 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800463 renderer.setMatrix(mMatrix);
464 }
465
Chris Craikc5493fb2013-06-19 16:58:58 -0700466 virtual void output(int level, uint32_t logFlags) const {
Romain Guy4e7b7722013-07-16 13:47:01 -0700467 if (mMatrix) {
468 OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
469 } else {
470 OP_LOGS("SetMatrix (reset)");
471 }
Chris Craik2af46352012-11-26 18:30:17 -0800472 }
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 Craikc5493fb2013-06-19 16:58:58 -0700489 virtual void output(int level, uint32_t logFlags) const {
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 Craikc5493fb2013-06-19 16:58:58 -0700533 virtual void output(int level, uint32_t logFlags) const {
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 Craikc5493fb2013-06-19 16:58:58 -0700562 virtual void output(int level, uint32_t logFlags) const {
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 Craikc5493fb2013-06-19 16:58:58 -0700583 virtual void output(int level, uint32_t logFlags) const {
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;
Chris Craik2af46352012-11-26 18:30:17 -0800593};
594
595class ResetShaderOp : public StateOp {
596public:
Chris Craik7273daa2013-03-28 11:25:24 -0700597 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800598 renderer.resetShader();
599 }
600
Chris Craikc5493fb2013-06-19 16:58:58 -0700601 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800602 OP_LOGS("ResetShader");
603 }
604
605 virtual const char* name() { return "ResetShader"; }
606};
607
608class SetupShaderOp : public StateOp {
609public:
610 SetupShaderOp(SkiaShader* shader)
611 : mShader(shader) {}
Chris Craik7273daa2013-03-28 11:25:24 -0700612 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800613 renderer.setupShader(mShader);
614 }
615
Chris Craikc5493fb2013-06-19 16:58:58 -0700616 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800617 OP_LOG("SetupShader, shader %p", mShader);
618 }
619
620 virtual const char* name() { return "SetupShader"; }
621
622private:
623 SkiaShader* mShader;
624};
625
626class ResetColorFilterOp : public StateOp {
627public:
Chris Craik7273daa2013-03-28 11:25:24 -0700628 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800629 renderer.resetColorFilter();
630 }
631
Chris Craikc5493fb2013-06-19 16:58:58 -0700632 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800633 OP_LOGS("ResetColorFilter");
634 }
635
636 virtual const char* name() { return "ResetColorFilter"; }
637};
638
639class SetupColorFilterOp : public StateOp {
640public:
641 SetupColorFilterOp(SkiaColorFilter* colorFilter)
642 : mColorFilter(colorFilter) {}
643
Chris Craik7273daa2013-03-28 11:25:24 -0700644 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800645 renderer.setupColorFilter(mColorFilter);
646 }
647
Chris Craikc5493fb2013-06-19 16:58:58 -0700648 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800649 OP_LOG("SetupColorFilter, filter %p", mColorFilter);
650 }
651
652 virtual const char* name() { return "SetupColorFilter"; }
653
654private:
655 SkiaColorFilter* mColorFilter;
656};
657
658class ResetShadowOp : public StateOp {
659public:
Chris Craik7273daa2013-03-28 11:25:24 -0700660 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800661 renderer.resetShadow();
662 }
663
Chris Craikc5493fb2013-06-19 16:58:58 -0700664 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800665 OP_LOGS("ResetShadow");
666 }
667
668 virtual const char* name() { return "ResetShadow"; }
669};
670
671class SetupShadowOp : public StateOp {
672public:
673 SetupShadowOp(float radius, float dx, float dy, int color)
674 : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
675
Chris Craik7273daa2013-03-28 11:25:24 -0700676 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800677 renderer.setupShadow(mRadius, mDx, mDy, mColor);
678 }
679
Chris Craikc5493fb2013-06-19 16:58:58 -0700680 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800681 OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
682 }
683
684 virtual const char* name() { return "SetupShadow"; }
685
686private:
687 float mRadius;
688 float mDx;
689 float mDy;
690 int mColor;
691};
692
693class ResetPaintFilterOp : public StateOp {
694public:
Chris Craik7273daa2013-03-28 11:25:24 -0700695 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800696 renderer.resetPaintFilter();
697 }
698
Chris Craikc5493fb2013-06-19 16:58:58 -0700699 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800700 OP_LOGS("ResetPaintFilter");
701 }
702
703 virtual const char* name() { return "ResetPaintFilter"; }
704};
705
706class SetupPaintFilterOp : public StateOp {
707public:
708 SetupPaintFilterOp(int clearBits, int setBits)
709 : mClearBits(clearBits), mSetBits(setBits) {}
710
Chris Craik7273daa2013-03-28 11:25:24 -0700711 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800712 renderer.setupPaintFilter(mClearBits, mSetBits);
713 }
714
Chris Craikc5493fb2013-06-19 16:58:58 -0700715 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800716 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
717 }
718
719 virtual const char* name() { return "SetupPaintFilter"; }
720
721private:
722 int mClearBits;
723 int mSetBits;
724};
725
Chris Craik2af46352012-11-26 18:30:17 -0800726///////////////////////////////////////////////////////////////////////////////
727// DRAW OPERATIONS - these are operations that can draw to the canvas's device
728///////////////////////////////////////////////////////////////////////////////
729
730class DrawBitmapOp : public DrawBoundedOp {
731public:
732 DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
Romain Guy3b748a42013-04-17 18:54:38 -0700733 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700734 mBitmap(bitmap), mAtlas(Caches::getInstance().assetAtlas) {
735 mEntry = mAtlas.getEntry(bitmap);
736 if (mEntry) {
737 mEntryGenerationId = mAtlas.getGenerationId();
738 mUvMapper = mEntry->uvMapper;
739 }
Romain Guy3b748a42013-04-17 18:54:38 -0700740 }
Chris Craik2af46352012-11-26 18:30:17 -0800741
Chris Craik527a3aa2013-03-04 10:19:31 -0800742 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -0700743 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
744 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800745 }
746
Romain Guy55b6f952013-06-27 15:27:09 -0700747 AssetAtlas::Entry* getAtlasEntry() {
748 // The atlas entry is stale, let's get a new one
749 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
750 mEntryGenerationId = mAtlas.getGenerationId();
751 mEntry = mAtlas.getEntry(mBitmap);
752 mUvMapper = mEntry->uvMapper;
753 }
754 return mEntry;
755 }
756
Chris Craik527a3aa2013-03-04 10:19:31 -0800757#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
758 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
759 texCoordsRect.xDim, texCoordsRect.yDim)
760
Romain Guy03c00b52013-06-20 18:30:28 -0700761 /**
762 * This multi-draw operation builds a mesh on the stack by generating a quad
763 * for each bitmap in the batch. This method is also responsible for dirtying
764 * the current layer, if any.
765 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800766 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700767 const Vector<OpStatePair>& ops, const Rect& bounds) {
768 const DeferredDisplayState& firstState = *(ops[0].state);
769 renderer.restoreDisplayState(firstState, true); // restore all but the clip
770
Chris Craik527a3aa2013-03-04 10:19:31 -0800771 TextureVertex vertices[6 * ops.size()];
772 TextureVertex* vertex = &vertices[0];
773
Romain Guy03c00b52013-06-20 18:30:28 -0700774 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700775 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700776
Romain Guy3b748a42013-04-17 18:54:38 -0700777 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
778 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800779 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700780 const DeferredDisplayState& state = *(ops[i].state);
781 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700782 // When we reach multiDraw(), the matrix can be either
783 // pureTranslate or simple (translate and/or scale).
784 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700785 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700786
787 Rect texCoords(0, 0, 1, 1);
Chris Craikc1c5f082013-09-11 16:23:37 -0700788 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700789
Chris Craik527a3aa2013-03-04 10:19:31 -0800790 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
791 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
792 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
793
794 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
795 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
796 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700797
798 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700799 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700800 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800801 }
802
Romain Guy55b6f952013-06-27 15:27:09 -0700803 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700804 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800805 }
806
Chris Craikc5493fb2013-06-19 16:58:58 -0700807 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800808 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
809 }
810
811 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800812
Chris Craikc1c5f082013-09-11 16:23:37 -0700813 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
814 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700815 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikd965bc52013-09-16 14:47:13 -0700816 deferInfo.mergeId = getAtlasEntry() ?
817 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700818
Chris Craikd965bc52013-09-16 14:47:13 -0700819 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
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
Chris Craikd965bc52013-09-16 14:47:13 -0700823 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
824 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700825 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
826 (mBitmap->getConfig() != SkBitmap::kA8_Config);
Chris Craikc3566d02013-02-04 16:16:33 -0800827 }
Chris Craik2af46352012-11-26 18:30:17 -0800828
Chris Craik527a3aa2013-03-04 10:19:31 -0800829 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800830protected:
831 SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700832 const AssetAtlas& mAtlas;
833 uint32_t mEntryGenerationId;
834 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700835 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800836};
837
838class DrawBitmapMatrixOp : public DrawBoundedOp {
839public:
840 DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
841 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
842 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
843 const mat4 transform(*matrix);
844 transform.mapRect(mLocalBounds);
845 }
846
Chris Craik527a3aa2013-03-04 10:19:31 -0800847 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800848 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
849 }
850
Chris Craikc5493fb2013-06-19 16:58:58 -0700851 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800852 OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
853 }
854
Chris Craik527a3aa2013-03-04 10:19:31 -0800855 virtual const char* name() { return "DrawBitmapMatrix"; }
856
Chris Craikc1c5f082013-09-11 16:23:37 -0700857 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
858 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700859 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800860 }
Chris Craik2af46352012-11-26 18:30:17 -0800861
862private:
863 SkBitmap* mBitmap;
864 SkMatrix* mMatrix;
865};
866
867class DrawBitmapRectOp : public DrawBoundedOp {
868public:
869 DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
870 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
871 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
872 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
873
Chris Craik527a3aa2013-03-04 10:19:31 -0800874 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800875 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
876 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
877 getPaint(renderer));
878 }
879
Chris Craikc5493fb2013-06-19 16:58:58 -0700880 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800881 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
882 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
883 }
884
885 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800886
Chris Craikc1c5f082013-09-11 16:23:37 -0700887 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
888 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700889 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800890 }
Chris Craik2af46352012-11-26 18:30:17 -0800891
892private:
893 SkBitmap* mBitmap;
894 Rect mSrc;
895};
896
897class DrawBitmapDataOp : public DrawBitmapOp {
898public:
899 DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
900 : DrawBitmapOp(bitmap, left, top, paint) {}
901
Chris Craik527a3aa2013-03-04 10:19:31 -0800902 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800903 return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
904 mLocalBounds.top, getPaint(renderer));
905 }
906
Chris Craikc5493fb2013-06-19 16:58:58 -0700907 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800908 OP_LOG("Draw bitmap %p", mBitmap);
909 }
910
911 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800912
Chris Craikc1c5f082013-09-11 16:23:37 -0700913 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
914 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700915 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800916 }
Chris Craik2af46352012-11-26 18:30:17 -0800917};
918
Chris Craik5d116762013-02-19 17:49:31 -0800919class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800920public:
921 DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
922 float* vertices, int* colors, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800923 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
924 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800925 mVertices(vertices), mColors(colors) {}
926
Chris Craik527a3aa2013-03-04 10:19:31 -0800927 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800928 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
929 mVertices, mColors, getPaint(renderer));
930 }
931
Chris Craikc5493fb2013-06-19 16:58:58 -0700932 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800933 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
934 }
935
936 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800937
Chris Craikc1c5f082013-09-11 16:23:37 -0700938 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
939 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700940 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800941 }
Chris Craik2af46352012-11-26 18:30:17 -0800942
943private:
944 SkBitmap* mBitmap;
945 int mMeshWidth;
946 int mMeshHeight;
947 float* mVertices;
948 int* mColors;
949};
950
951class DrawPatchOp : public DrawBoundedOp {
952public:
Romain Guy3b748a42013-04-17 18:54:38 -0700953 DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch,
Romain Guy03c00b52013-06-20 18:30:28 -0700954 float left, float top, float right, float bottom, SkPaint* paint)
955 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700956 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
957 mAtlas(Caches::getInstance().assetAtlas) {
958 mEntry = mAtlas.getEntry(bitmap);
959 if (mEntry) {
960 mEntryGenerationId = mAtlas.getGenerationId();
961 }
Romain Guy3b748a42013-04-17 18:54:38 -0700962 };
Chris Craik2af46352012-11-26 18:30:17 -0800963
Romain Guy55b6f952013-06-27 15:27:09 -0700964 AssetAtlas::Entry* getAtlasEntry() {
965 // The atlas entry is stale, let's get a new one
966 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
967 mEntryGenerationId = mAtlas.getGenerationId();
968 mEntry = mAtlas.getEntry(mBitmap);
969 }
970 return mEntry;
971 }
972
Romain Guy03c00b52013-06-20 18:30:28 -0700973 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700974 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
975 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700976 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700977 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700978 mGenerationId = cache.getGenerationId();
979 }
Romain Guy03c00b52013-06-20 18:30:28 -0700980 return mMesh;
981 }
982
983 /**
984 * This multi-draw operation builds an indexed mesh on the stack by copying
985 * and transforming the vertices of each 9-patch in the batch. This method
986 * is also responsible for dirtying the current layer, if any.
987 */
988 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700989 const Vector<OpStatePair>& ops, const Rect& bounds) {
990 const DeferredDisplayState& firstState = *(ops[0].state);
991 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700992
993 // Batches will usually contain a small number of items so it's
994 // worth performing a first iteration to count the exact number
995 // of vertices we need in the new mesh
996 uint32_t totalVertices = 0;
997 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700998 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700999 }
1000
1001 const bool hasLayer = renderer.hasLayer();
1002
1003 uint32_t indexCount = 0;
1004
1005 TextureVertex vertices[totalVertices];
1006 TextureVertex* vertex = &vertices[0];
1007
1008 // Create a mesh that contains the transformed vertices for all the
1009 // 9-patch objects that are part of the batch. Note that onDefer()
1010 // enforces ops drawn by this function to have a pure translate or
1011 // identity matrix
1012 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001013 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
1014 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -07001015 const Patch* opMesh = patchOp->getMesh(renderer);
1016 uint32_t vertexCount = opMesh->verticesCount;
1017 if (vertexCount == 0) continue;
1018
1019 // We use the bounds to know where to translate our vertices
1020 // Using patchOp->state.mBounds wouldn't work because these
1021 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -07001022 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -07001023 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -07001024 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -07001025 patchOp->mLocalBounds.top + 0.5f);
1026
1027 // Copy & transform all the vertices for the current operation
1028 TextureVertex* opVertices = opMesh->vertices;
1029 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
1030 TextureVertex::set(vertex++,
1031 opVertices->position[0] + tx, opVertices->position[1] + ty,
1032 opVertices->texture[0], opVertices->texture[1]);
1033 }
1034
1035 // Dirty the current layer if possible. When the 9-patch does not
1036 // contain empty quads we can take a shortcut and simply set the
1037 // dirty rect to the object's bounds.
1038 if (hasLayer) {
1039 if (!opMesh->hasEmptyQuads) {
1040 renderer.dirtyLayer(tx, ty,
1041 tx + patchOp->mLocalBounds.getWidth(),
1042 ty + patchOp->mLocalBounds.getHeight());
1043 } else {
1044 const size_t count = opMesh->quads.size();
1045 for (size_t i = 0; i < count; i++) {
1046 const Rect& quadBounds = opMesh->quads[i];
1047 const float x = tx + quadBounds.left;
1048 const float y = ty + quadBounds.top;
1049 renderer.dirtyLayer(x, y,
1050 x + quadBounds.getWidth(), y + quadBounds.getHeight());
1051 }
1052 }
1053 }
1054
1055 indexCount += opMesh->indexCount;
1056 }
1057
Romain Guy55b6f952013-06-27 15:27:09 -07001058 return renderer.drawPatches(mBitmap, getAtlasEntry(),
1059 &vertices[0], indexCount, getPaint(renderer));
Romain Guy03c00b52013-06-20 18:30:28 -07001060 }
1061
1062 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -07001063 // We're not calling the public variant of drawPatch() here
1064 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy55b6f952013-06-27 15:27:09 -07001065 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -07001066 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
1067 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -08001068 }
1069
Chris Craikc5493fb2013-06-19 16:58:58 -07001070 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001071 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
1072 }
1073
1074 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -08001075
Chris Craikc1c5f082013-09-11 16:23:37 -07001076 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1077 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001078 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy7f6d6b02013-08-06 13:49:28 -07001079 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -07001080 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
1081 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -07001082 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -08001083 }
Chris Craik2af46352012-11-26 18:30:17 -08001084
1085private:
1086 SkBitmap* mBitmap;
Romain Guy3b748a42013-04-17 18:54:38 -07001087 Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -07001088
Romain Guy4c2547f2013-06-11 16:19:24 -07001089 uint32_t mGenerationId;
1090 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -07001091
Romain Guy55b6f952013-06-27 15:27:09 -07001092 const AssetAtlas& mAtlas;
1093 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -07001094 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -08001095};
1096
1097class DrawColorOp : public DrawOp {
1098public:
1099 DrawColorOp(int color, SkXfermode::Mode mode)
1100 : DrawOp(0), mColor(color), mMode(mode) {};
1101
Chris Craik527a3aa2013-03-04 10:19:31 -08001102 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001103 return renderer.drawColor(mColor, mMode);
1104 }
1105
Chris Craikc5493fb2013-06-19 16:58:58 -07001106 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001107 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
1108 }
1109
1110 virtual const char* name() { return "DrawColor"; }
1111
1112private:
1113 int mColor;
1114 SkXfermode::Mode mMode;
1115};
1116
1117class DrawStrokableOp : public DrawBoundedOp {
1118public:
1119 DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
1120 : DrawBoundedOp(left, top, right, bottom, paint) {};
1121
Chris Craikc1c5f082013-09-11 16:23:37 -07001122 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001123 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001124 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001125 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001126 }
1127 return true;
1128 }
Chris Craikc3566d02013-02-04 16:16:33 -08001129
Chris Craikc1c5f082013-09-11 16:23:37 -07001130 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1131 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -08001132 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001133 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001134 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001135 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001136 DeferredDisplayList::kOpBatch_AlphaVertices :
1137 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001138 }
Chris Craikc3566d02013-02-04 16:16:33 -08001139 }
Chris Craik2af46352012-11-26 18:30:17 -08001140};
1141
1142class DrawRectOp : public DrawStrokableOp {
1143public:
1144 DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
1145 : DrawStrokableOp(left, top, right, bottom, paint) {}
1146
Chris Craik527a3aa2013-03-04 10:19:31 -08001147 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001148 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1149 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1150 }
1151
Chris Craikc5493fb2013-06-19 16:58:58 -07001152 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001153 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
1154 }
1155
Chris Craikc1c5f082013-09-11 16:23:37 -07001156 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1157 const DeferredDisplayState& state) {
1158 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1159 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -07001160 mPaint->getStyle() == SkPaint::kFill_Style;
1161 }
1162
Chris Craik2af46352012-11-26 18:30:17 -08001163 virtual const char* name() { return "DrawRect"; }
1164};
1165
Chris Craik5d116762013-02-19 17:49:31 -08001166class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001167public:
1168 DrawRectsOp(const float* rects, int count, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001169 : DrawBoundedOp(rects, count, paint),
1170 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001171
Chris Craik527a3aa2013-03-04 10:19:31 -08001172 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001173 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1174 }
1175
Chris Craikc5493fb2013-06-19 16:58:58 -07001176 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001177 OP_LOG("Draw Rects count %d", mCount);
1178 }
1179
1180 virtual const char* name() { return "DrawRects"; }
1181
Chris Craikc1c5f082013-09-11 16:23:37 -07001182 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1183 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001184 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001185 }
1186
Chris Craik2af46352012-11-26 18:30:17 -08001187private:
1188 const float* mRects;
1189 int mCount;
1190};
1191
1192class DrawRoundRectOp : public DrawStrokableOp {
1193public:
1194 DrawRoundRectOp(float left, float top, float right, float bottom,
1195 float rx, float ry, SkPaint* paint)
1196 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1197
Chris Craik527a3aa2013-03-04 10:19:31 -08001198 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001199 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1200 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1201 }
1202
Chris Craikc5493fb2013-06-19 16:58:58 -07001203 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001204 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
1205 }
1206
1207 virtual const char* name() { return "DrawRoundRect"; }
1208
1209private:
1210 float mRx;
1211 float mRy;
1212};
1213
1214class DrawCircleOp : public DrawStrokableOp {
1215public:
1216 DrawCircleOp(float x, float y, float radius, SkPaint* paint)
1217 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1218 mX(x), mY(y), mRadius(radius) {}
1219
Chris Craik527a3aa2013-03-04 10:19:31 -08001220 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001221 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1222 }
1223
Chris Craikc5493fb2013-06-19 16:58:58 -07001224 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001225 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1226 }
1227
1228 virtual const char* name() { return "DrawCircle"; }
1229
1230private:
1231 float mX;
1232 float mY;
1233 float mRadius;
1234};
1235
1236class DrawOvalOp : public DrawStrokableOp {
1237public:
1238 DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
1239 : DrawStrokableOp(left, top, right, bottom, paint) {}
1240
Chris Craik527a3aa2013-03-04 10:19:31 -08001241 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001242 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1243 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1244 }
1245
Chris Craikc5493fb2013-06-19 16:58:58 -07001246 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001247 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
1248 }
1249
1250 virtual const char* name() { return "DrawOval"; }
1251};
1252
1253class DrawArcOp : public DrawStrokableOp {
1254public:
1255 DrawArcOp(float left, float top, float right, float bottom,
1256 float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
1257 : DrawStrokableOp(left, top, right, bottom, paint),
1258 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1259
Chris Craik527a3aa2013-03-04 10:19:31 -08001260 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001261 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1262 mLocalBounds.right, mLocalBounds.bottom,
1263 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1264 }
1265
Chris Craikc5493fb2013-06-19 16:58:58 -07001266 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001267 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
1268 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1269 }
1270
1271 virtual const char* name() { return "DrawArc"; }
1272
1273private:
1274 float mStartAngle;
1275 float mSweepAngle;
1276 bool mUseCenter;
1277};
1278
1279class DrawPathOp : public DrawBoundedOp {
1280public:
1281 DrawPathOp(SkPath* path, SkPaint* paint)
1282 : DrawBoundedOp(paint), mPath(path) {
1283 float left, top, offset;
1284 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001285 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001286 left -= offset;
1287 top -= offset;
1288 mLocalBounds.set(left, top, left + width, top + height);
1289 }
1290
Chris Craik527a3aa2013-03-04 10:19:31 -08001291 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001292 return renderer.drawPath(mPath, getPaint(renderer));
1293 }
1294
Chris Craikc1c5f082013-09-11 16:23:37 -07001295 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1296 const DeferredDisplayState& state) {
Romain Guyca89e2a2013-03-08 17:44:20 -08001297 SkPaint* paint = getPaint(renderer);
1298 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001299
Chris Craik28ce94a2013-05-31 11:38:03 -07001300 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001301 }
1302
Chris Craikc5493fb2013-06-19 16:58:58 -07001303 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001304 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1305 }
1306
1307 virtual const char* name() { return "DrawPath"; }
1308
1309private:
1310 SkPath* mPath;
1311};
1312
Chris Craikc3566d02013-02-04 16:16:33 -08001313class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001314public:
1315 DrawLinesOp(float* points, int count, SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001316 : DrawBoundedOp(points, count, paint),
1317 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001318 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001319 }
1320
Chris Craik527a3aa2013-03-04 10:19:31 -08001321 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001322 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1323 }
1324
Chris Craikc5493fb2013-06-19 16:58:58 -07001325 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001326 OP_LOG("Draw Lines count %d", mCount);
1327 }
1328
1329 virtual const char* name() { return "DrawLines"; }
1330
Chris Craikc1c5f082013-09-11 16:23:37 -07001331 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1332 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001333 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001334 DeferredDisplayList::kOpBatch_AlphaVertices :
1335 DeferredDisplayList::kOpBatch_Vertices;
1336 }
1337
Chris Craik2af46352012-11-26 18:30:17 -08001338protected:
1339 float* mPoints;
1340 int mCount;
1341};
1342
1343class DrawPointsOp : public DrawLinesOp {
1344public:
1345 DrawPointsOp(float* points, int count, SkPaint* paint)
1346 : DrawLinesOp(points, count, paint) {}
1347
Chris Craik527a3aa2013-03-04 10:19:31 -08001348 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001349 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1350 }
1351
Chris Craikc5493fb2013-06-19 16:58:58 -07001352 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001353 OP_LOG("Draw Points count %d", mCount);
1354 }
1355
1356 virtual const char* name() { return "DrawPoints"; }
1357};
1358
1359class DrawSomeTextOp : public DrawOp {
1360public:
1361 DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
1362 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1363
Chris Craikc5493fb2013-06-19 16:58:58 -07001364 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001365 OP_LOG("Draw some text, %d bytes", mBytesCount);
1366 }
Chris Craikc3566d02013-02-04 16:16:33 -08001367
Chris Craikc1c5f082013-09-11 16:23:37 -07001368 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1369 const DeferredDisplayState& state) {
Romain Guy0f667532013-03-01 14:31:04 -08001370 SkPaint* paint = getPaint(renderer);
1371 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1372 fontRenderer.precache(paint, mText, mCount, mat4::identity());
Romain Guy0f667532013-03-01 14:31:04 -08001373
Chris Craik28ce94a2013-05-31 11:38:03 -07001374 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craikc3566d02013-02-04 16:16:33 -08001375 DeferredDisplayList::kOpBatch_Text :
1376 DeferredDisplayList::kOpBatch_ColorText;
1377 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001378
Chris Craik2af46352012-11-26 18:30:17 -08001379protected:
1380 const char* mText;
1381 int mBytesCount;
1382 int mCount;
1383};
1384
1385class DrawTextOnPathOp : public DrawSomeTextOp {
1386public:
1387 DrawTextOnPathOp(const char* text, int bytesCount, int count,
1388 SkPath* path, float hOffset, float vOffset, SkPaint* paint)
1389 : DrawSomeTextOp(text, bytesCount, count, paint),
1390 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1391 /* TODO: inherit from DrawBounded and init mLocalBounds */
1392 }
1393
Chris Craik527a3aa2013-03-04 10:19:31 -08001394 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001395 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1396 mHOffset, mVOffset, getPaint(renderer));
1397 }
1398
1399 virtual const char* name() { return "DrawTextOnPath"; }
1400
1401private:
1402 SkPath* mPath;
1403 float mHOffset;
1404 float mVOffset;
1405};
1406
1407class DrawPosTextOp : public DrawSomeTextOp {
1408public:
1409 DrawPosTextOp(const char* text, int bytesCount, int count,
1410 const float* positions, SkPaint* paint)
1411 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1412 /* TODO: inherit from DrawBounded and init mLocalBounds */
1413 }
1414
Chris Craik527a3aa2013-03-04 10:19:31 -08001415 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001416 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1417 }
1418
1419 virtual const char* name() { return "DrawPosText"; }
1420
1421private:
1422 const float* mPositions;
1423};
1424
1425class DrawTextOp : public DrawBoundedOp {
1426public:
1427 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craik41541822013-05-03 16:35:54 -07001428 const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds)
1429 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1430 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Romain Guybd3055f2013-03-13 16:14:47 -07001431 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
Chris Craik2af46352012-11-26 18:30:17 -08001432 }
1433
Chris Craikc1c5f082013-09-11 16:23:37 -07001434 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1435 const DeferredDisplayState& state) {
Romain Guy0f667532013-03-01 14:31:04 -08001436 SkPaint* paint = getPaint(renderer);
1437 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Romain Guybd3055f2013-03-13 16:14:47 -07001438 const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1439 if (mPrecacheTransform != transform) {
1440 fontRenderer.precache(paint, mText, mCount, transform);
1441 mPrecacheTransform = transform;
1442 }
Chris Craik28ce94a2013-05-31 11:38:03 -07001443 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001444 DeferredDisplayList::kOpBatch_Text :
1445 DeferredDisplayList::kOpBatch_ColorText;
1446
Kévin PETIT73fc5582014-02-13 11:03:40 +00001447 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001448
1449 // don't merge decorated text - the decorations won't draw in order
1450 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
1451 SkPaint::kStrikeThruText_Flag));
Chris Craik28ce94a2013-05-31 11:38:03 -07001452 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations &&
1453 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001454 }
1455
Chris Craik527a3aa2013-03-04 10:19:31 -08001456 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001457 Rect bounds;
Chris Craikc1c5f082013-09-11 16:23:37 -07001458 getLocalBounds(renderer.getDrawModifiers(), bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001459 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Romain Guy9b5a1a22013-08-09 14:06:29 -07001460 mPositions, getPaint(renderer), mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001461 }
1462
Chris Craik527a3aa2013-03-04 10:19:31 -08001463 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -07001464 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001465 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001466 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001467 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001468 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001469 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001470
Chris Craikc1c5f082013-09-11 16:23:37 -07001471 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001472 // quickReject() will not occure in drawText() so we can use mLocalBounds
1473 // directly, we do not need to account for shadow by calling getLocalBounds()
Chris Craik527a3aa2013-03-04 10:19:31 -08001474 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001475 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1476 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001477 }
1478 return status;
1479 }
1480
Chris Craikc5493fb2013-06-19 16:58:58 -07001481 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001482 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1483 }
1484
1485 virtual const char* name() { return "DrawText"; }
1486
1487private:
1488 const char* mText;
1489 int mBytesCount;
1490 int mCount;
1491 float mX;
1492 float mY;
1493 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001494 float mTotalAdvance;
Romain Guybd3055f2013-03-13 16:14:47 -07001495 mat4 mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001496};
1497
1498///////////////////////////////////////////////////////////////////////////////
1499// SPECIAL DRAW OPERATIONS
1500///////////////////////////////////////////////////////////////////////////////
1501
1502class DrawFunctorOp : public DrawOp {
1503public:
1504 DrawFunctorOp(Functor* functor)
1505 : DrawOp(0), mFunctor(functor) {}
1506
Chris Craik527a3aa2013-03-04 10:19:31 -08001507 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001508 renderer.startMark("GL functor");
1509 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1510 renderer.endMark();
1511 return ret;
1512 }
1513
Chris Craikc5493fb2013-06-19 16:58:58 -07001514 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001515 OP_LOG("Draw Functor %p", mFunctor);
1516 }
1517
1518 virtual const char* name() { return "DrawFunctor"; }
1519
1520private:
1521 Functor* mFunctor;
1522};
1523
Chris Craik5d116762013-02-19 17:49:31 -08001524class DrawDisplayListOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001525public:
1526 DrawDisplayListOp(DisplayList* displayList, int flags)
Chris Craik5d116762013-02-19 17:49:31 -08001527 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
1528 mDisplayList(displayList), mFlags(flags) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001529
Chet Haasedd671592013-04-19 14:54:34 -07001530 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1531 bool useQuickReject) {
Chris Craikc3566d02013-02-04 16:16:33 -08001532 if (mDisplayList && mDisplayList->isRenderable()) {
Chris Craikff785832013-03-08 13:12:16 -08001533 mDisplayList->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001534 }
Chris Craikc3566d02013-02-04 16:16:33 -08001535 }
Chet Haasedd671592013-04-19 14:54:34 -07001536 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1537 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -08001538 if (mDisplayList && mDisplayList->isRenderable()) {
1539 mDisplayList->replay(replayStruct, level + 1);
1540 }
1541 }
Chris Craik2af46352012-11-26 18:30:17 -08001542
Chris Craika08f95c2013-03-15 17:24:33 -07001543 // NOT USED since replay() is overridden
Chris Craik527a3aa2013-03-04 10:19:31 -08001544 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001545 return DrawGlInfo::kStatusDone;
1546 }
Chris Craikff785832013-03-08 13:12:16 -08001547
Chris Craikc5493fb2013-06-19 16:58:58 -07001548 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001549 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
Chris Craikff785832013-03-08 13:12:16 -08001550 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
Chris Craik2af46352012-11-26 18:30:17 -08001551 mDisplayList->output(level + 1);
1552 }
1553 }
1554
1555 virtual const char* name() { return "DrawDisplayList"; }
1556
1557private:
1558 DisplayList* mDisplayList;
1559 int mFlags;
1560};
1561
1562class DrawLayerOp : public DrawOp {
1563public:
Chris Craika08f95c2013-03-15 17:24:33 -07001564 DrawLayerOp(Layer* layer, float x, float y)
1565 : DrawOp(0), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001566
Chris Craik527a3aa2013-03-04 10:19:31 -08001567 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001568 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001569 }
1570
Chris Craikc5493fb2013-06-19 16:58:58 -07001571 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001572 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1573 }
1574
1575 virtual const char* name() { return "DrawLayer"; }
1576
1577private:
1578 Layer* mLayer;
1579 float mX;
1580 float mY;
1581};
1582
1583}; // namespace uirenderer
1584}; // namespace android
1585
1586#endif // ANDROID_HWUI_DISPLAY_OPERATION_H