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    uint32_t getGenerationId() {
86        return mGenerationId;
87    }
88
89    void setMatrix(SkMatrix* matrix) {
90        updateLocalMatrix(matrix);
91        mGenerationId++;
92    }
93
94    void updateLocalMatrix(const SkMatrix* matrix) {
95        if (matrix) {
96            mat4 localMatrix(*matrix);
97            mShaderMatrix.loadInverse(localMatrix);
98        } else {
99            mShaderMatrix.loadIdentity();
100        }
101    }
102
103    void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
104
105protected:
106    SkiaShader() {
107    }
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    TextureCache* mTextureCache;
122    GradientCache* mGradientCache;
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 bitmap.
138 */
139struct SkiaBitmapShader: public SkiaShader {
140    ANDROID_API SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
141            SkShader::TileMode tileY, SkMatrix* matrix, bool blend);
142    SkiaShader* copy();
143
144    void describe(ProgramDescription& description, const Extensions& extensions);
145    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
146            GLuint* textureUnit);
147
148private:
149    SkiaBitmapShader() {
150    }
151
152    SkBitmap* mBitmap;
153    Texture* mTexture;
154    GLenum mWrapS;
155    GLenum mWrapT;
156}; // struct SkiaBitmapShader
157
158/**
159 * A shader that draws a linear gradient.
160 */
161struct SkiaLinearGradientShader: public SkiaShader {
162    ANDROID_API SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions,
163            int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
164    ~SkiaLinearGradientShader();
165    SkiaShader* copy();
166
167    void describe(ProgramDescription& description, const Extensions& extensions);
168    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
169            GLuint* textureUnit);
170
171private:
172    SkiaLinearGradientShader() {
173    }
174
175    bool mIsSimple;
176    float* mBounds;
177    uint32_t* mColors;
178    float* mPositions;
179    int mCount;
180}; // struct SkiaLinearGradientShader
181
182/**
183 * A shader that draws a sweep gradient.
184 */
185struct SkiaSweepGradientShader: public SkiaShader {
186    ANDROID_API SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions,
187            int count, SkShader* key, SkMatrix* matrix, bool blend);
188    ~SkiaSweepGradientShader();
189    SkiaShader* copy();
190
191    virtual void describe(ProgramDescription& description, const Extensions& extensions);
192    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
193            GLuint* textureUnit);
194
195protected:
196    SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
197            int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
198    SkiaSweepGradientShader() {
199    }
200
201    bool mIsSimple;
202    uint32_t* mColors;
203    float* mPositions;
204    int mCount;
205}; // struct SkiaSweepGradientShader
206
207/**
208 * A shader that draws a circular gradient.
209 */
210struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
211    ANDROID_API SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors,
212            float* positions, int count, SkShader* key,SkShader::TileMode tileMode,
213            SkMatrix* matrix, bool blend);
214    SkiaShader* copy();
215
216    void describe(ProgramDescription& description, const Extensions& extensions);
217
218private:
219    SkiaCircularGradientShader() {
220    }
221}; // struct SkiaCircularGradientShader
222
223/**
224 * A shader that draws two shaders, composited with an xfermode.
225 */
226struct SkiaComposeShader: public SkiaShader {
227    ANDROID_API SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode,
228            SkShader* key);
229    ~SkiaComposeShader();
230    SkiaShader* copy();
231
232    void set(TextureCache* textureCache, GradientCache* gradientCache);
233
234    void describe(ProgramDescription& description, const Extensions& extensions);
235    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
236            GLuint* textureUnit);
237
238private:
239    SkiaComposeShader(): mCleanup(false) {
240    }
241
242    void cleanup() {
243        mCleanup = true;
244    }
245
246    SkiaShader* mFirst;
247    SkiaShader* mSecond;
248    SkXfermode::Mode mMode;
249
250    bool mCleanup;
251}; // struct SkiaComposeShader
252
253}; // namespace uirenderer
254}; // namespace android
255
256#endif // ANDROID_HWUI_SKIA_SHADER_H
257