SkiaShader.h revision 3f085429fd47ebd32ac2463b3eae2a5a6c17be25
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_SKIA_SHADER_H
18#define ANDROID_HWUI_SKIA_SHADER_H
19
20#include <SkShader.h>
21#include <SkXfermode.h>
22
23#include <GLES2/gl2.h>
24
25#include <cutils/compiler.h>
26
27#include "Extensions.h"
28#include "ProgramCache.h"
29#include "TextureCache.h"
30#include "GradientCache.h"
31#include "Snapshot.h"
32
33namespace android {
34namespace uirenderer {
35
36class Caches;
37
38///////////////////////////////////////////////////////////////////////////////
39// Base shader
40///////////////////////////////////////////////////////////////////////////////
41
42/**
43 * Represents a Skia shader. A shader will modify the GL context and active
44 * program to recreate the original effect.
45 */
46class SkiaShader {
47public:
48    /**
49     * Type of Skia shader in use.
50     */
51    enum Type {
52        kNone,
53        kBitmap,
54        kLinearGradient,
55        kCircularGradient,
56        kSweepGradient,
57        kCompose
58    };
59
60    ANDROID_API SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
61            SkShader::TileMode tileY, const SkMatrix* matrix, bool blend);
62    virtual ~SkiaShader();
63
64    virtual SkiaShader* copy() = 0;
65    void copyFrom(const SkiaShader& shader);
66
67    virtual void describe(ProgramDescription& description, const Extensions& extensions);
68    virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
69            GLuint* textureUnit);
70
71    inline SkShader* getSkShader() {
72        return mKey;
73    }
74
75    inline bool blend() const {
76        return mBlend;
77    }
78
79    Type type() const {
80        return mType;
81    }
82
83    virtual void setCaches(Caches& caches) {
84        mCaches = &caches;
85    }
86
87    uint32_t getGenerationId() {
88        return mGenerationId;
89    }
90
91    void setMatrix(const SkMatrix* matrix) {
92        updateLocalMatrix(matrix);
93        mGenerationId++;
94    }
95
96    void updateLocalMatrix(const SkMatrix* matrix) {
97        if (matrix) {
98            mat4 localMatrix(*matrix);
99            mShaderMatrix.loadInverse(localMatrix);
100        } else {
101            mShaderMatrix.loadIdentity();
102        }
103    }
104
105    void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
106
107protected:
108    SkiaShader();
109
110    /**
111     * The appropriate texture unit must have been activated prior to invoking
112     * this method.
113     */
114    inline void bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT);
115
116    Type mType;
117    SkShader* mKey;
118    SkShader::TileMode mTileX;
119    SkShader::TileMode mTileY;
120    bool mBlend;
121
122    Caches* mCaches;
123
124    mat4 mUnitMatrix;
125    mat4 mShaderMatrix;
126
127private:
128    uint32_t mGenerationId;
129}; // struct SkiaShader
130
131
132///////////////////////////////////////////////////////////////////////////////
133// Implementations
134///////////////////////////////////////////////////////////////////////////////
135
136/**
137 * A shader that draws a layer.
138 */
139struct SkiaLayerShader: public SkiaShader {
140    SkiaLayerShader(Layer* layer, const SkMatrix* matrix);
141    SkiaShader* copy();
142
143    void describe(ProgramDescription& description, const Extensions& extensions);
144    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
145            GLuint* textureUnit);
146
147private:
148    SkiaLayerShader() {
149    }
150
151    Layer* mLayer;
152}; // struct SkiaLayerShader
153
154/**
155 * A shader that draws a bitmap.
156 */
157struct SkiaBitmapShader: public SkiaShader {
158    ANDROID_API SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
159            SkShader::TileMode tileY, SkMatrix* matrix, bool blend);
160    SkiaShader* copy();
161
162    void describe(ProgramDescription& description, const Extensions& extensions);
163    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
164            GLuint* textureUnit);
165
166private:
167    SkiaBitmapShader() : mBitmap(NULL), mTexture(NULL) {
168    }
169
170    SkBitmap* mBitmap;
171    Texture* mTexture;
172    GLenum mWrapS;
173    GLenum mWrapT;
174}; // struct SkiaBitmapShader
175
176/**
177 * A shader that draws a linear gradient.
178 */
179struct SkiaLinearGradientShader: public SkiaShader {
180    ANDROID_API SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions,
181            int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
182    ~SkiaLinearGradientShader();
183    SkiaShader* copy();
184
185    void describe(ProgramDescription& description, const Extensions& extensions);
186    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
187            GLuint* textureUnit);
188
189private:
190    SkiaLinearGradientShader() {
191    }
192
193    bool mIsSimple;
194    float* mBounds;
195    uint32_t* mColors;
196    float* mPositions;
197    int mCount;
198}; // struct SkiaLinearGradientShader
199
200/**
201 * A shader that draws a sweep gradient.
202 */
203struct SkiaSweepGradientShader: public SkiaShader {
204    ANDROID_API SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions,
205            int count, SkShader* key, SkMatrix* matrix, bool blend);
206    ~SkiaSweepGradientShader();
207    SkiaShader* copy();
208
209    virtual void describe(ProgramDescription& description, const Extensions& extensions);
210    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
211            GLuint* textureUnit);
212
213protected:
214    SkiaSweepGradientShader(Type type, uint32_t* colors, float* positions,
215            int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
216    SkiaSweepGradientShader() {
217    }
218
219    bool mIsSimple;
220    uint32_t* mColors;
221    float* mPositions;
222    int mCount;
223}; // struct SkiaSweepGradientShader
224
225/**
226 * A shader that draws a circular gradient.
227 */
228struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
229    ANDROID_API SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors,
230            float* positions, int count, SkShader* key,SkShader::TileMode tileMode,
231            SkMatrix* matrix, bool blend);
232    SkiaShader* copy();
233
234    void describe(ProgramDescription& description, const Extensions& extensions);
235
236private:
237    SkiaCircularGradientShader() {
238    }
239}; // struct SkiaCircularGradientShader
240
241/**
242 * A shader that draws two shaders, composited with an xfermode.
243 */
244struct SkiaComposeShader: public SkiaShader {
245    ANDROID_API SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode,
246            SkShader* key);
247    ~SkiaComposeShader();
248    SkiaShader* copy();
249
250    void setCaches(Caches& caches) {
251        SkiaShader::setCaches(caches);
252        mFirst->setCaches(caches);
253        mSecond->setCaches(caches);
254    }
255
256    void describe(ProgramDescription& description, const Extensions& extensions);
257    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
258            GLuint* textureUnit);
259
260private:
261    SkiaComposeShader(): mCleanup(false) {
262    }
263
264    void cleanup() {
265        mCleanup = true;
266    }
267
268    SkiaShader* mFirst;
269    SkiaShader* mSecond;
270    SkXfermode::Mode mMode;
271
272    bool mCleanup;
273}; // struct SkiaComposeShader
274
275}; // namespace uirenderer
276}; // namespace android
277
278#endif // ANDROID_HWUI_SKIA_SHADER_H
279