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