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