1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
18#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
19
20#include <SkMatrix.h>
21#include <SkPaint.h>
22#include <SkPath.h>
23#include <cutils/compiler.h>
24
25#include "DisplayListLogBuffer.h"
26#include "RenderNode.h"
27#include "ResourceCache.h"
28
29namespace android {
30namespace uirenderer {
31
32///////////////////////////////////////////////////////////////////////////////
33// Defines
34///////////////////////////////////////////////////////////////////////////////
35
36// Debug
37#if DEBUG_DISPLAY_LIST
38    #define DISPLAY_LIST_LOGD(...) ALOGD(__VA_ARGS__)
39#else
40    #define DISPLAY_LIST_LOGD(...)
41#endif
42
43///////////////////////////////////////////////////////////////////////////////
44// Display list
45///////////////////////////////////////////////////////////////////////////////
46
47class DeferredDisplayList;
48class DeferredLayerUpdater;
49class DisplayListRenderer;
50class DisplayListOp;
51class DrawOp;
52class StateOp;
53
54/**
55 * Records drawing commands in a display list for later playback into an OpenGLRenderer.
56 */
57class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer {
58public:
59    DisplayListRenderer();
60    virtual ~DisplayListRenderer();
61
62    void insertReorderBarrier(bool enableReorder);
63
64    DisplayListData* finishRecording();
65
66// ----------------------------------------------------------------------------
67// Frame state operations
68// ----------------------------------------------------------------------------
69    virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
70    virtual void finish();
71    virtual void interrupt();
72    virtual void resume();
73
74// ----------------------------------------------------------------------------
75// Canvas state operations
76// ----------------------------------------------------------------------------
77    // Save (layer)
78    virtual int save(int flags);
79    virtual void restore();
80    virtual void restoreToCount(int saveCount);
81    virtual int saveLayer(float left, float top, float right, float bottom,
82            const SkPaint* paint, int flags);
83
84    // Matrix
85    virtual void translate(float dx, float dy, float dz = 0.0f);
86    virtual void rotate(float degrees);
87    virtual void scale(float sx, float sy);
88    virtual void skew(float sx, float sy);
89
90    virtual void setMatrix(const SkMatrix& matrix);
91    virtual void concatMatrix(const SkMatrix& matrix);
92
93    // Clip
94    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
95    virtual bool clipPath(const SkPath* path, SkRegion::Op op);
96    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
97
98    // Misc - should be implemented with SkPaint inspection
99    virtual void resetPaintFilter();
100    virtual void setupPaintFilter(int clearBits, int setBits);
101
102    bool isCurrentTransformSimple() {
103        return currentTransform()->isSimple();
104    }
105
106// ----------------------------------------------------------------------------
107// Canvas draw operations
108// ----------------------------------------------------------------------------
109    virtual status_t drawColor(int color, SkXfermode::Mode mode);
110
111    // Bitmap-based
112    virtual status_t drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
113    virtual status_t drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
114            float srcRight, float srcBottom, float dstLeft, float dstTop,
115            float dstRight, float dstBottom, const SkPaint* paint);
116    virtual status_t drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint);
117    virtual status_t drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
118            const float* vertices, const int* colors, const SkPaint* paint);
119    virtual status_t drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
120            float left, float top, float right, float bottom, const SkPaint* paint);
121
122    // Shapes
123    virtual status_t drawRect(float left, float top, float right, float bottom,
124            const SkPaint* paint);
125    virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
126    virtual status_t drawRoundRect(float left, float top, float right, float bottom,
127            float rx, float ry, const SkPaint* paint);
128    virtual status_t drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
129                CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
130                CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
131                CanvasPropertyPaint* paint);
132    virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
133    virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
134                CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
135    virtual status_t drawOval(float left, float top, float right, float bottom,
136            const SkPaint* paint);
137    virtual status_t drawArc(float left, float top, float right, float bottom,
138            float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint);
139    virtual status_t drawPath(const SkPath* path, const SkPaint* paint);
140    virtual status_t drawLines(const float* points, int count, const SkPaint* paint);
141    virtual status_t drawPoints(const float* points, int count, const SkPaint* paint);
142
143    // Text
144    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
145            const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
146            DrawOpMode drawOpMode = kDrawOpMode_Immediate);
147    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path,
148            float hOffset, float vOffset, const SkPaint* paint);
149    virtual status_t drawPosText(const char* text, int bytesCount, int count,
150            const float* positions, const SkPaint* paint);
151
152// ----------------------------------------------------------------------------
153// Canvas draw operations - special
154// ----------------------------------------------------------------------------
155    virtual status_t drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
156    virtual status_t drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags);
157
158    // TODO: rename for consistency
159    virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
160
161    void setHighContrastText(bool highContrastText) {
162        mHighContrastText = highContrastText;
163    }
164private:
165    enum DeferredBarrierType {
166        kBarrier_None,
167        kBarrier_InOrder,
168        kBarrier_OutOfOrder,
169    };
170
171    void flushRestoreToCount();
172    void flushTranslate();
173    void flushReorderBarrier();
174
175    LinearAllocator& alloc() { return mDisplayListData->allocator; }
176
177    // Each method returns final index of op
178    size_t addOpAndUpdateChunk(DisplayListOp* op);
179    // flushes any deferred operations, and appends the op
180    size_t flushAndAddOp(DisplayListOp* op);
181
182    size_t addStateOp(StateOp* op);
183    size_t addDrawOp(DrawOp* op);
184    size_t addRenderNodeOp(DrawRenderNodeOp* op);
185
186
187    template<class T>
188    inline const T* refBuffer(const T* srcBuffer, int32_t count) {
189        if (!srcBuffer) return NULL;
190
191        T* dstBuffer = (T*) mDisplayListData->allocator.alloc(count * sizeof(T));
192        memcpy(dstBuffer, srcBuffer, count * sizeof(T));
193        return dstBuffer;
194    }
195
196    inline char* refText(const char* text, size_t byteLength) {
197        return (char*) refBuffer<uint8_t>((uint8_t*)text, byteLength);
198    }
199
200    inline const SkPath* refPath(const SkPath* path) {
201        if (!path) return NULL;
202
203        const SkPath* pathCopy = mPathMap.valueFor(path);
204        if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
205            SkPath* newPathCopy = new SkPath(*path);
206            newPathCopy->setSourcePath(path);
207
208            pathCopy = newPathCopy;
209            // replaceValueFor() performs an add if the entry doesn't exist
210            mPathMap.replaceValueFor(path, pathCopy);
211            mDisplayListData->paths.add(pathCopy);
212        }
213        if (mDisplayListData->sourcePaths.indexOf(path) < 0) {
214            mResourceCache.incrementRefcount(path);
215            mDisplayListData->sourcePaths.add(path);
216        }
217        return pathCopy;
218    }
219
220    inline const SkPaint* refPaint(const SkPaint* paint) {
221        if (!paint) return NULL;
222
223        const SkPaint* paintCopy = mPaintMap.valueFor(paint);
224        if (paintCopy == NULL
225                || paintCopy->getGenerationID() != paint->getGenerationID()
226                // We can't compare shader pointers because that will always
227                // change as we do partial copying via wrapping. However, if the
228                // shader changes the paint generationID will have changed and
229                // so we don't hit this comparison anyway
230                || !(paint->getShader() && paintCopy->getShader()
231                        && paint->getShader()->getGenerationID() == paintCopy->getShader()->getGenerationID())) {
232            paintCopy = copyPaint(paint);
233            // replaceValueFor() performs an add if the entry doesn't exist
234            mPaintMap.replaceValueFor(paint, paintCopy);
235        }
236
237        return paintCopy;
238    }
239
240    inline SkPaint* copyPaint(const SkPaint* paint) {
241        if (!paint) return NULL;
242        SkPaint* paintCopy = new SkPaint(*paint);
243        if (paint->getShader()) {
244            SkShader* shaderCopy = SkShader::CreateLocalMatrixShader(
245                    paint->getShader(), paint->getShader()->getLocalMatrix());
246            paintCopy->setShader(shaderCopy);
247            paintCopy->setGenerationID(paint->getGenerationID());
248            shaderCopy->setGenerationID(paint->getShader()->getGenerationID());
249            shaderCopy->unref();
250        }
251        mDisplayListData->paints.add(paintCopy);
252        return paintCopy;
253    }
254
255    inline const SkRegion* refRegion(const SkRegion* region) {
256        if (!region) {
257            return region;
258        }
259
260        const SkRegion* regionCopy = mRegionMap.valueFor(region);
261        // TODO: Add generation ID to SkRegion
262        if (regionCopy == NULL) {
263            regionCopy = new SkRegion(*region);
264            // replaceValueFor() performs an add if the entry doesn't exist
265            mRegionMap.replaceValueFor(region, regionCopy);
266            mDisplayListData->regions.add(regionCopy);
267        }
268
269        return regionCopy;
270    }
271
272    inline const SkBitmap* refBitmap(const SkBitmap* bitmap) {
273        // Note that this assumes the bitmap is immutable. There are cases this won't handle
274        // correctly, such as creating the bitmap from scratch, drawing with it, changing its
275        // contents, and drawing again. The only fix would be to always copy it the first time,
276        // which doesn't seem worth the extra cycles for this unlikely case.
277        mDisplayListData->bitmapResources.add(bitmap);
278        mResourceCache.incrementRefcount(bitmap);
279        return bitmap;
280    }
281
282    inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) {
283        mDisplayListData->ownedBitmapResources.add(bitmap);
284        mResourceCache.incrementRefcount(bitmap);
285        return bitmap;
286    }
287
288    inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
289        mDisplayListData->patchResources.add(patch);
290        mResourceCache.incrementRefcount(patch);
291        return patch;
292    }
293
294    DefaultKeyedVector<const SkPaint*, const SkPaint*> mPaintMap;
295    DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
296    DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
297
298    ResourceCache& mResourceCache;
299    DisplayListData* mDisplayListData;
300
301    float mTranslateX;
302    float mTranslateY;
303    bool mHasDeferredTranslate;
304    DeferredBarrierType mDeferredBarrierType;
305    bool mHighContrastText;
306
307    int mRestoreSaveCount;
308
309    friend class RenderNode;
310
311}; // class DisplayListRenderer
312
313}; // namespace uirenderer
314}; // namespace android
315
316#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
317