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