101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy/*
201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * Copyright (C) 2011 The Android Open Source Project
301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy *
401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * you may not use this file except in compliance with the License.
601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * You may obtain a copy of the License at
701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy *
801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy *
1001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * Unless required by applicable law or agreed to in writing, software
1101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
1201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * See the License for the specific language governing permissions and
1401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * limitations under the License.
1501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy */
1601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
1701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#ifndef ANDROID_HWUI_SHAPE_CACHE_H
1801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#define ANDROID_HWUI_SHAPE_CACHE_H
1901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
2001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#include <GLES2/gl2.h>
2101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
22ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy#include <SkBitmap.h>
2301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#include <SkCanvas.h>
24ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy#include <SkPaint.h>
25ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy#include <SkPath.h>
2601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#include <SkRect.h>
2701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
28ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy#include "Debug.h"
2901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#include "Properties.h"
30ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy#include "Texture.h"
31ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy#include "utils/Compare.h"
32ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy#include "utils/GenerationCache.h"
3301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
3401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guynamespace android {
3501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guynamespace uirenderer {
3601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
3701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
3801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// Defines
3901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
4001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
4101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// Debug
4201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#if DEBUG_SHAPES
435baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    #define SHAPE_LOGD(...) ALOGD(__VA_ARGS__)
4401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#else
4501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    #define SHAPE_LOGD(...)
4601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#endif
4701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
4801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
4901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// Classes
5001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
5101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
5201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy/**
53ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy * Alpha texture used to represent a path.
54ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy */
55ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guystruct PathTexture: public Texture {
56ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    PathTexture(): Texture() {
57ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    }
58ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy
59ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    /**
60ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     * Left coordinate of the path bounds.
61ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     */
62ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    float left;
63ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    /**
64ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     * Top coordinate of the path bounds.
65ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     */
66ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    float top;
67ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    /**
68ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     * Offset to draw the path at the correct origin.
69ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     */
70ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    float offset;
71ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy}; // struct PathTexture
72ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy
73ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy/**
7401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * Describe a shape in the shape cache.
7501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy */
7601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guystruct ShapeCacheEntry {
7701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    enum ShapeType {
7801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        kShapeNone,
79c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        kShapeRect,
8001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        kShapeRoundRect,
8101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        kShapeCircle,
8201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        kShapeOval,
83ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy        kShapeArc,
84ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy        kShapePath
8501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    };
8601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
8701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    ShapeCacheEntry() {
8801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        shapeType = kShapeNone;
8901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        join = SkPaint::kDefault_Join;
9001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        cap = SkPaint::kDefault_Cap;
9101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        style = SkPaint::kFill_Style;
921af23a32d879db330eb5a08b21090ec60b604a32Romain Guy        float v = 4.0f;
931af23a32d879db330eb5a08b21090ec60b604a32Romain Guy        miter = *(uint32_t*) &v;
941af23a32d879db330eb5a08b21090ec60b604a32Romain Guy        v = 1.0f;
951af23a32d879db330eb5a08b21090ec60b604a32Romain Guy        strokeWidth = *(uint32_t*) &v;
961af23a32d879db330eb5a08b21090ec60b604a32Romain Guy        pathEffect = NULL;
9701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
9801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
9901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    ShapeCacheEntry(ShapeType type, SkPaint* paint) {
10001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        shapeType = type;
10101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        join = paint->getStrokeJoin();
10201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        cap = paint->getStrokeCap();
10301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        float v = paint->getStrokeMiter();
10401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        miter = *(uint32_t*) &v;
10501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        v = paint->getStrokeWidth();
10601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        strokeWidth = *(uint32_t*) &v;
10701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        style = paint->getStyle();
108b29cfbf768eab959b31410aafc0a99e20249e9d7Romain Guy        pathEffect = paint->getPathEffect();
10901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
11001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
11101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    virtual ~ShapeCacheEntry() {
11201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
11301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
11401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    ShapeType shapeType;
11501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    SkPaint::Join join;
11601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    SkPaint::Cap cap;
11701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    SkPaint::Style style;
11801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t miter;
11901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t strokeWidth;
120b29cfbf768eab959b31410aafc0a99e20249e9d7Romain Guy    SkPathEffect* pathEffect;
12101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
12201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    bool operator<(const ShapeCacheEntry& rhs) const {
12301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        LTE_INT(shapeType) {
12401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            LTE_INT(join) {
12501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                LTE_INT(cap) {
12601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                    LTE_INT(style) {
12701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                        LTE_INT(miter) {
12801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                            LTE_INT(strokeWidth) {
129b29cfbf768eab959b31410aafc0a99e20249e9d7Romain Guy                                LTE_INT(pathEffect) {
130b29cfbf768eab959b31410aafc0a99e20249e9d7Romain Guy                                    return lessThan(rhs);
131b29cfbf768eab959b31410aafc0a99e20249e9d7Romain Guy                                }
13201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                            }
13301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                        }
13401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                    }
13501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                }
13601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            }
13701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
13801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return false;
13901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
14001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
14101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyprotected:
14201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    virtual bool lessThan(const ShapeCacheEntry& rhs) const {
14301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return false;
14401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
14501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}; // struct ShapeCacheEntry
14601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
14701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
14801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guystruct RoundRectShapeCacheEntry: public ShapeCacheEntry {
14901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    RoundRectShapeCacheEntry(float width, float height, float rx, float ry, SkPaint* paint):
15001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            ShapeCacheEntry(ShapeCacheEntry::kShapeRoundRect, paint) {
15101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mWidth = *(uint32_t*) &width;
15201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mHeight = *(uint32_t*) &height;
15301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mRx = *(uint32_t*) &rx;
15401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mRy = *(uint32_t*) &ry;
15501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
15601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
15701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    RoundRectShapeCacheEntry(): ShapeCacheEntry() {
15801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mWidth = 0;
15901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mHeight = 0;
16001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mRx = 0;
16101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mRy = 0;
16201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
16301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
16401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    bool lessThan(const ShapeCacheEntry& r) const {
16501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        const RoundRectShapeCacheEntry& rhs = (const RoundRectShapeCacheEntry&) r;
16601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        LTE_INT(mWidth) {
16701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            LTE_INT(mHeight) {
16801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                LTE_INT(mRx) {
16901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                    LTE_INT(mRy) {
17001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                        return false;
17101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                    }
17201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy                }
17301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            }
17401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
17501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return false;
17601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
17701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
17801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyprivate:
17901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t mWidth;
18001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t mHeight;
18101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t mRx;
18201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t mRy;
18301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}; // RoundRectShapeCacheEntry
18401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
18501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guystruct CircleShapeCacheEntry: public ShapeCacheEntry {
18601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    CircleShapeCacheEntry(float radius, SkPaint* paint):
18701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            ShapeCacheEntry(ShapeCacheEntry::kShapeCircle, paint) {
18801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mRadius = *(uint32_t*) &radius;
18901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
19001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
19101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    CircleShapeCacheEntry(): ShapeCacheEntry() {
19201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mRadius = 0;
19301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
19401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
19501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    bool lessThan(const ShapeCacheEntry& r) const {
19601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        const CircleShapeCacheEntry& rhs = (const CircleShapeCacheEntry&) r;
19701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        LTE_INT(mRadius) {
19801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            return false;
19901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
20001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return false;
20101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
20201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
20301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyprivate:
20401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t mRadius;
20501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}; // CircleShapeCacheEntry
20601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
207c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guystruct OvalShapeCacheEntry: public ShapeCacheEntry {
208c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    OvalShapeCacheEntry(float width, float height, SkPaint* paint):
209c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy            ShapeCacheEntry(ShapeCacheEntry::kShapeOval, paint) {
210c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        mWidth = *(uint32_t*) &width;
211c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        mHeight = *(uint32_t*) &height;
212c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    }
213c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
214c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    OvalShapeCacheEntry(): ShapeCacheEntry() {
215c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        mWidth = mHeight = 0;
216c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    }
217c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
218c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    bool lessThan(const ShapeCacheEntry& r) const {
219c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        const OvalShapeCacheEntry& rhs = (const OvalShapeCacheEntry&) r;
220c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        LTE_INT(mWidth) {
221c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy            LTE_INT(mHeight) {
222c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy                return false;
223c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy            }
224c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        }
225c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        return false;
226c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    }
227c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
228c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guyprivate:
229c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    uint32_t mWidth;
230c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    uint32_t mHeight;
231c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy}; // OvalShapeCacheEntry
232c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
233c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guystruct RectShapeCacheEntry: public ShapeCacheEntry {
234c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    RectShapeCacheEntry(float width, float height, SkPaint* paint):
235c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy            ShapeCacheEntry(ShapeCacheEntry::kShapeRect, paint) {
236c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        mWidth = *(uint32_t*) &width;
237c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        mHeight = *(uint32_t*) &height;
238c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    }
239c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
240c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    RectShapeCacheEntry(): ShapeCacheEntry() {
241c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        mWidth = mHeight = 0;
242c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    }
243c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
244c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    bool lessThan(const ShapeCacheEntry& r) const {
245c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        const RectShapeCacheEntry& rhs = (const RectShapeCacheEntry&) r;
246c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        LTE_INT(mWidth) {
247c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy            LTE_INT(mHeight) {
248c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy                return false;
249c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy            }
250c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        }
251c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy        return false;
252c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    }
253c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
254c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guyprivate:
255c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    uint32_t mWidth;
256c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    uint32_t mHeight;
257c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy}; // RectShapeCacheEntry
258c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
2598b2f5267f16c295f12faab810527cd6311997e34Romain Guystruct ArcShapeCacheEntry: public ShapeCacheEntry {
2608b2f5267f16c295f12faab810527cd6311997e34Romain Guy    ArcShapeCacheEntry(float width, float height, float startAngle, float sweepAngle,
2618b2f5267f16c295f12faab810527cd6311997e34Romain Guy            bool useCenter, SkPaint* paint):
2628b2f5267f16c295f12faab810527cd6311997e34Romain Guy            ShapeCacheEntry(ShapeCacheEntry::kShapeArc, paint) {
2638b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mWidth = *(uint32_t*) &width;
2648b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mHeight = *(uint32_t*) &height;
2658b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mStartAngle = *(uint32_t*) &startAngle;
2668b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mSweepAngle = *(uint32_t*) &sweepAngle;
2678b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mUseCenter = useCenter ? 1 : 0;
2688b2f5267f16c295f12faab810527cd6311997e34Romain Guy    }
2698b2f5267f16c295f12faab810527cd6311997e34Romain Guy
2708b2f5267f16c295f12faab810527cd6311997e34Romain Guy    ArcShapeCacheEntry(): ShapeCacheEntry() {
2718b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mWidth = 0;
2728b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mHeight = 0;
2738b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mStartAngle = 0;
2748b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mSweepAngle = 0;
2758b2f5267f16c295f12faab810527cd6311997e34Romain Guy        mUseCenter = 0;
2768b2f5267f16c295f12faab810527cd6311997e34Romain Guy    }
2778b2f5267f16c295f12faab810527cd6311997e34Romain Guy
2788b2f5267f16c295f12faab810527cd6311997e34Romain Guy    bool lessThan(const ShapeCacheEntry& r) const {
2798b2f5267f16c295f12faab810527cd6311997e34Romain Guy        const ArcShapeCacheEntry& rhs = (const ArcShapeCacheEntry&) r;
2808b2f5267f16c295f12faab810527cd6311997e34Romain Guy        LTE_INT(mWidth) {
2818b2f5267f16c295f12faab810527cd6311997e34Romain Guy            LTE_INT(mHeight) {
2828b2f5267f16c295f12faab810527cd6311997e34Romain Guy                LTE_INT(mStartAngle) {
2838b2f5267f16c295f12faab810527cd6311997e34Romain Guy                    LTE_INT(mSweepAngle) {
2848b2f5267f16c295f12faab810527cd6311997e34Romain Guy                        LTE_INT(mUseCenter) {
2858b2f5267f16c295f12faab810527cd6311997e34Romain Guy                            return false;
2868b2f5267f16c295f12faab810527cd6311997e34Romain Guy                        }
2878b2f5267f16c295f12faab810527cd6311997e34Romain Guy                    }
2888b2f5267f16c295f12faab810527cd6311997e34Romain Guy                }
2898b2f5267f16c295f12faab810527cd6311997e34Romain Guy            }
2908b2f5267f16c295f12faab810527cd6311997e34Romain Guy        }
2918b2f5267f16c295f12faab810527cd6311997e34Romain Guy        return false;
2928b2f5267f16c295f12faab810527cd6311997e34Romain Guy    }
2938b2f5267f16c295f12faab810527cd6311997e34Romain Guy
2948b2f5267f16c295f12faab810527cd6311997e34Romain Guyprivate:
2958b2f5267f16c295f12faab810527cd6311997e34Romain Guy    uint32_t mWidth;
2968b2f5267f16c295f12faab810527cd6311997e34Romain Guy    uint32_t mHeight;
2978b2f5267f16c295f12faab810527cd6311997e34Romain Guy    uint32_t mStartAngle;
2988b2f5267f16c295f12faab810527cd6311997e34Romain Guy    uint32_t mSweepAngle;
2998b2f5267f16c295f12faab810527cd6311997e34Romain Guy    uint32_t mUseCenter;
3008b2f5267f16c295f12faab810527cd6311997e34Romain Guy}; // ArcShapeCacheEntry
3018b2f5267f16c295f12faab810527cd6311997e34Romain Guy
30201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy/**
30301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
30401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * Any texture added to the cache causing the cache to grow beyond the maximum
30501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy * allowed size will also cause the oldest texture to be kicked out.
30601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy */
30701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<typename Entry>
30801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyclass ShapeCache: public OnEntryRemoved<Entry, PathTexture*> {
30901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guypublic:
310ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    ShapeCache(const char* name, const char* propertyName, float defaultSize);
31101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    ~ShapeCache();
31201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
31301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    /**
31401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     * Used as a callback when an entry is removed from the cache.
31501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     * Do not invoke directly.
31601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     */
31701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    void operator()(Entry& path, PathTexture*& texture);
31801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
31901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    /**
32001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     * Clears the cache. This causes all textures to be deleted.
32101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     */
32201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    void clear();
32301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
32401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    /**
32501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     * Sets the maximum size of the cache in bytes.
32601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     */
32701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    void setMaxSize(uint32_t maxSize);
32801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    /**
32901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     * Returns the maximum size of the cache in bytes.
33001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     */
33101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t getMaxSize();
33201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    /**
33301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     * Returns the current size of the cache in bytes.
33401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy     */
33501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t getSize();
33601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
33701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyprotected:
33801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    PathTexture* addTexture(const Entry& entry, const SkPath *path, const SkPaint* paint);
339fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    PathTexture* addTexture(const Entry& entry, SkBitmap* bitmap);
340fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    void addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture);
341fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
342fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    /**
343fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy     * Ensures there is enough space in the cache for a texture of the specified
344fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy     * dimensions.
345fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy     */
346fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    void purgeCache(uint32_t width, uint32_t height);
347fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
348fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height);
349fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    void initPaint(SkPaint& paint);
350fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
351fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    bool checkTextureSize(uint32_t width, uint32_t height);
35201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
35301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    PathTexture* get(Entry entry) {
35401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return mCache.get(entry);
35501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
35601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
35701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    void removeTexture(PathTexture* texture);
35801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
35901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    GenerationCache<Entry, PathTexture*> mCache;
36001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t mSize;
36101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    uint32_t mMaxSize;
36201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    GLuint mMaxTextureSize;
36301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
364ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    char* mName;
36501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    bool mDebugEnabled;
366ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy
367ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guyprivate:
368ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    /**
369ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     * Generates the texture from a bitmap into the specified texture structure.
370ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy     */
371ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    void generateTexture(SkBitmap& bitmap, Texture* texture);
372ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy
373ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    void init();
37401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}; // class ShapeCache
37501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
37601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyclass RoundRectShapeCache: public ShapeCache<RoundRectShapeCacheEntry> {
37701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guypublic:
37801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    RoundRectShapeCache();
37901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
38001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    PathTexture* getRoundRect(float width, float height, float rx, float ry, SkPaint* paint);
38101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}; // class RoundRectShapeCache
38201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
38301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyclass CircleShapeCache: public ShapeCache<CircleShapeCacheEntry> {
38401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guypublic:
38501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    CircleShapeCache();
38601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
38701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    PathTexture* getCircle(float radius, SkPaint* paint);
388c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy}; // class CircleShapeCache
389c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
390c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guyclass OvalShapeCache: public ShapeCache<OvalShapeCacheEntry> {
391c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guypublic:
392c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    OvalShapeCache();
393c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
394c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    PathTexture* getOval(float width, float height, SkPaint* paint);
395c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy}; // class OvalShapeCache
396c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
397c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guyclass RectShapeCache: public ShapeCache<RectShapeCacheEntry> {
398c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guypublic:
399c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    RectShapeCache();
40001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
401c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy    PathTexture* getRect(float width, float height, SkPaint* paint);
402c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy}; // class RectShapeCache
40301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
4048b2f5267f16c295f12faab810527cd6311997e34Romain Guyclass ArcShapeCache: public ShapeCache<ArcShapeCacheEntry> {
4058b2f5267f16c295f12faab810527cd6311997e34Romain Guypublic:
4068b2f5267f16c295f12faab810527cd6311997e34Romain Guy    ArcShapeCache();
4078b2f5267f16c295f12faab810527cd6311997e34Romain Guy
4088b2f5267f16c295f12faab810527cd6311997e34Romain Guy    PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
4098b2f5267f16c295f12faab810527cd6311997e34Romain Guy            bool useCenter, SkPaint* paint);
4108b2f5267f16c295f12faab810527cd6311997e34Romain Guy}; // class ArcShapeCache
4118b2f5267f16c295f12faab810527cd6311997e34Romain Guy
41201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
41301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// Constructors/destructor
41401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
41501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
41601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
417ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain GuyShapeCache<Entry>::ShapeCache(const char* name, const char* propertyName, float defaultSize):
41801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mCache(GenerationCache<ShapeCacheEntry, PathTexture*>::kUnlimitedCapacity),
419ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy        mSize(0), mMaxSize(MB(defaultSize)) {
42001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    char property[PROPERTY_VALUE_MAX];
421ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    if (property_get(propertyName, property, NULL) > 0) {
422c9855a53edfac818dc68714557185977556f849dRomain Guy        INIT_LOGD("  Setting %s cache size to %sMB", name, property);
42301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        setMaxSize(MB(atof(property)));
42401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    } else {
425c9855a53edfac818dc68714557185977556f849dRomain Guy        INIT_LOGD("  Using default %s cache size of %.2fMB", name, defaultSize);
42601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
42701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
428ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    size_t len = strlen(name);
429ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    mName = new char[len + 1];
430ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    strcpy(mName, name);
431ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    mName[len] = '\0';
432ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy
43301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    init();
43401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
43501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
43601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
43701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain GuyShapeCache<Entry>::~ShapeCache() {
43801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    mCache.clear();
439ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy    delete[] mName;
44001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
44101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
44201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
44301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyvoid ShapeCache<Entry>::init() {
44401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    mCache.setOnEntryRemovedListener(this);
44501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
44601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    GLint maxTextureSize;
44701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
44801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    mMaxTextureSize = maxTextureSize;
44901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
45001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    mDebugEnabled = readDebugLevel() & kDebugCaches;
45101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
45201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
45301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
45401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// Size management
45501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
45601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
45701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
45801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyuint32_t ShapeCache<Entry>::getSize() {
45901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    return mSize;
46001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
46101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
46201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
46301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyuint32_t ShapeCache<Entry>::getMaxSize() {
46401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    return mMaxSize;
46501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
46601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
46701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
46801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyvoid ShapeCache<Entry>::setMaxSize(uint32_t maxSize) {
46901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    mMaxSize = maxSize;
47001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    while (mSize > mMaxSize) {
47101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mCache.removeOldest();
47201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
47301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
47401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
47501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
47601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// Callbacks
47701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
47801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
47901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
48001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyvoid ShapeCache<Entry>::operator()(Entry& path, PathTexture*& texture) {
48101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    removeTexture(texture);
48201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
48301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
48401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
48501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// Caching
48601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy///////////////////////////////////////////////////////////////////////////////
48701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
48801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
48901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyvoid ShapeCache<Entry>::removeTexture(PathTexture* texture) {
49001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    if (texture) {
49101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        const uint32_t size = texture->width * texture->height;
49201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mSize -= size;
49301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
494ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy        SHAPE_LOGD("ShapeCache::callback: delete %s: name, size, mSize = %d, %d, %d",
495ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy                mName, texture->id, size, mSize);
49601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (mDebugEnabled) {
4975baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            ALOGD("Shape %s deleted, size = %d", mName, size);
49801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
49901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
50001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        glDeleteTextures(1, &texture->id);
50101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        delete texture;
50201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
50301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
50401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
505fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guyvoid computePathBounds(const SkPath* path, const SkPaint* paint,
506fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy        float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
507fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guyvoid computeBounds(const SkRect& bounds, const SkPaint* paint,
50833f6beb10f98e8ba96250e284876d607055d278dRomain Guy        float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
50933f6beb10f98e8ba96250e284876d607055d278dRomain Guy
510fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guystatic PathTexture* createTexture(float left, float top, float offset,
511fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy        uint32_t width, uint32_t height, uint32_t id) {
512fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    PathTexture* texture = new PathTexture;
513fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    texture->left = left;
514fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    texture->top = top;
515fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    texture->offset = offset;
516fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    texture->width = width;
517fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    texture->height = height;
518fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    texture->generation = id;
519fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    return texture;
520fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy}
52198029c825b9234e6b90721d910cc180885fcab1dRomain Guy
522fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guytemplate<class Entry>
523fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guyvoid ShapeCache<Entry>::purgeCache(uint32_t width, uint32_t height) {
52401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    const uint32_t size = width * height;
52501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    // Don't even try to cache a bitmap that's bigger than the cache
52601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    if (size < mMaxSize) {
52701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        while (mSize + size > mMaxSize) {
52801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            mCache.removeOldest();
52901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
53001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
531fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy}
53201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
533fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guytemplate<class Entry>
534fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guyvoid ShapeCache<Entry>::initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
53501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    bitmap.setConfig(SkBitmap::kA8_Config, width, height);
53601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    bitmap.allocPixels();
53701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    bitmap.eraseColor(0);
538fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy}
53901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
540fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guytemplate<class Entry>
541fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guyvoid ShapeCache<Entry>::initPaint(SkPaint& paint) {
54201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    // Make sure the paint is opaque, color, alpha, filter, etc.
54301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    // will be applied later when compositing the alpha8 texture
544fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    paint.setColor(0xff000000);
545fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    paint.setAlpha(255);
546fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    paint.setColorFilter(NULL);
547fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    paint.setMaskFilter(NULL);
548fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    paint.setShader(NULL);
54901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
550fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    SkSafeUnref(paint.setXfermode(mode));
551fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy}
552fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
553fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guytemplate<class Entry>
554fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guybool ShapeCache<Entry>::checkTextureSize(uint32_t width, uint32_t height) {
555fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    if (width > mMaxTextureSize || height > mMaxTextureSize) {
556fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy        ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
557fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy                mName, width, height, mMaxTextureSize, mMaxTextureSize);
558fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy        return false;
559fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    }
560fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    return true;
561fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy}
562fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
563fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guytemplate<class Entry>
564fdd6fc1beb5076a630c7066b8b1731995636c09fRomain GuyPathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
565fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy        const SkPaint* paint) {
566fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
567fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    float left, top, offset;
568fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    uint32_t width, height;
569fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    computePathBounds(path, paint, left, top, offset, width, height);
570fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
571fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    if (!checkTextureSize(width, height)) return NULL;
572fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
573fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    purgeCache(width, height);
574fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
575fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    SkBitmap bitmap;
576fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    initBitmap(bitmap, width, height);
577fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
578fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    SkPaint pathPaint(*paint);
579fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    initPaint(pathPaint);
58001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
58101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    SkCanvas canvas(bitmap);
58233f6beb10f98e8ba96250e284876d607055d278dRomain Guy    canvas.translate(-left + offset, -top + offset);
58301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    canvas.drawPath(*path, pathPaint);
58401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
585fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    PathTexture* texture = createTexture(left, top, offset, width, height, path->getGenerationID());
586fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    addTexture(entry, &bitmap, texture);
587fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
588fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    return texture;
589fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy}
590fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy
591fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guytemplate<class Entry>
592fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guyvoid ShapeCache<Entry>::addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture) {
593fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    generateTexture(*bitmap, texture);
59401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
595fdd6fc1beb5076a630c7066b8b1731995636c09fRomain Guy    uint32_t size = texture->width * texture->height;
59601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    if (size < mMaxSize) {
59701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mSize += size;
598ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy        SHAPE_LOGD("ShapeCache::get: create %s: name, size, mSize = %d, %d, %d",
599ff26a0c1c905dc1ec53b1bab860b80f2976d59beRomain Guy                mName, texture->id, size, mSize);
60001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (mDebugEnabled) {
6015baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            ALOGD("Shape %s created, size = %d", mName, size);
60201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
60301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        mCache.put(entry, texture);
60401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    } else {
60501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        texture->cleanup = true;
60601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
60701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
60801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
60901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
61001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyvoid ShapeCache<Entry>::clear() {
61101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    mCache.clear();
61201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
61301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
61401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guytemplate<class Entry>
61501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guyvoid ShapeCache<Entry>::generateTexture(SkBitmap& bitmap, Texture* texture) {
61601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    SkAutoLockPixels alp(bitmap);
61701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    if (!bitmap.readyToDraw()) {
6183762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Cannot generate texture from bitmap");
61901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return;
62001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    }
62101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
62201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    glGenTextures(1, &texture->id);
62301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
62401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    glBindTexture(GL_TEXTURE_2D, texture->id);
62501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    // Textures are Alpha8
62601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
62701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
62801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    texture->blend = true;
62901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
63001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels());
63101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
632d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy    texture->setFilter(GL_LINEAR);
633d21b6e1fe337b35f62cf2028e9bd0637fd009a75Romain Guy    texture->setWrap(GL_CLAMP_TO_EDGE);
63401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}
63501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
63601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}; // namespace uirenderer
63701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy}; // namespace android
63801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
63901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy#endif // ANDROID_HWUI_SHAPE_CACHE_H
640