| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ANDROID_HWUI_SKIA_SHADER_H |
| #define ANDROID_HWUI_SKIA_SHADER_H |
| |
| #include <SkShader.h> |
| #include <SkXfermode.h> |
| |
| #include <GLES2/gl2.h> |
| |
| #include <cutils/compiler.h> |
| |
| #include "Extensions.h" |
| #include "ProgramCache.h" |
| #include "TextureCache.h" |
| #include "GradientCache.h" |
| #include "Snapshot.h" |
| |
| namespace android { |
| namespace uirenderer { |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Base shader |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Represents a Skia shader. A shader will modify the GL context and active |
| * program to recreate the original effect. |
| */ |
| struct SkiaShader { |
| /** |
| * Type of Skia shader in use. |
| */ |
| enum Type { |
| kNone, |
| kBitmap, |
| kLinearGradient, |
| kCircularGradient, |
| kSweepGradient, |
| kCompose |
| }; |
| |
| ANDROID_API SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX, |
| SkShader::TileMode tileY, SkMatrix* matrix, bool blend); |
| virtual ~SkiaShader(); |
| |
| virtual SkiaShader* copy() = 0; |
| void copyFrom(const SkiaShader& shader); |
| |
| virtual void describe(ProgramDescription& description, const Extensions& extensions); |
| virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, |
| GLuint* textureUnit); |
| |
| inline SkShader *getSkShader() { |
| return mKey; |
| } |
| |
| inline bool blend() const { |
| return mBlend; |
| } |
| |
| Type type() const { |
| return mType; |
| } |
| |
| virtual void set(TextureCache* textureCache, GradientCache* gradientCache) { |
| mTextureCache = textureCache; |
| mGradientCache = gradientCache; |
| } |
| |
| virtual void updateTransforms(Program* program, const mat4& modelView, |
| const Snapshot& snapshot) { |
| } |
| |
| uint32_t getGenerationId() { |
| return mGenerationId; |
| } |
| |
| void setMatrix(SkMatrix* matrix) { |
| updateLocalMatrix(matrix); |
| mGenerationId++; |
| } |
| |
| void updateLocalMatrix(const SkMatrix* matrix) { |
| if (matrix) { |
| mat4 localMatrix(*matrix); |
| mShaderMatrix.loadInverse(localMatrix); |
| } else { |
| mShaderMatrix.loadIdentity(); |
| } |
| } |
| |
| void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView); |
| |
| protected: |
| SkiaShader() { |
| } |
| |
| /** |
| * The appropriate texture unit must have been activated prior to invoking |
| * this method. |
| */ |
| inline void bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT); |
| |
| Type mType; |
| SkShader* mKey; |
| SkShader::TileMode mTileX; |
| SkShader::TileMode mTileY; |
| bool mBlend; |
| |
| TextureCache* mTextureCache; |
| GradientCache* mGradientCache; |
| |
| mat4 mUnitMatrix; |
| mat4 mShaderMatrix; |
| |
| private: |
| uint32_t mGenerationId; |
| }; // struct SkiaShader |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Implementations |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * A shader that draws a bitmap. |
| */ |
| struct SkiaBitmapShader: public SkiaShader { |
| ANDROID_API SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX, |
| SkShader::TileMode tileY, SkMatrix* matrix, bool blend); |
| SkiaShader* copy(); |
| |
| void describe(ProgramDescription& description, const Extensions& extensions); |
| void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, |
| GLuint* textureUnit); |
| void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); |
| |
| private: |
| SkiaBitmapShader() { |
| } |
| |
| /** |
| * This method does not work for n == 0. |
| */ |
| inline bool isPowerOfTwo(unsigned int n) { |
| return !(n & (n - 1)); |
| } |
| |
| SkBitmap* mBitmap; |
| Texture* mTexture; |
| GLenum mWrapS; |
| GLenum mWrapT; |
| }; // struct SkiaBitmapShader |
| |
| /** |
| * A shader that draws a linear gradient. |
| */ |
| struct SkiaLinearGradientShader: public SkiaShader { |
| ANDROID_API SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions, |
| int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); |
| ~SkiaLinearGradientShader(); |
| SkiaShader* copy(); |
| |
| void describe(ProgramDescription& description, const Extensions& extensions); |
| void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, |
| GLuint* textureUnit); |
| void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); |
| |
| private: |
| SkiaLinearGradientShader() { |
| } |
| |
| float* mBounds; |
| uint32_t* mColors; |
| float* mPositions; |
| int mCount; |
| }; // struct SkiaLinearGradientShader |
| |
| /** |
| * A shader that draws a sweep gradient. |
| */ |
| struct SkiaSweepGradientShader: public SkiaShader { |
| ANDROID_API SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, |
| int count, SkShader* key, SkMatrix* matrix, bool blend); |
| ~SkiaSweepGradientShader(); |
| SkiaShader* copy(); |
| |
| virtual void describe(ProgramDescription& description, const Extensions& extensions); |
| void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, |
| GLuint* textureUnit); |
| void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); |
| |
| protected: |
| SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions, |
| int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); |
| SkiaSweepGradientShader() { |
| } |
| |
| uint32_t* mColors; |
| float* mPositions; |
| int mCount; |
| }; // struct SkiaSweepGradientShader |
| |
| /** |
| * A shader that draws a circular gradient. |
| */ |
| struct SkiaCircularGradientShader: public SkiaSweepGradientShader { |
| ANDROID_API SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, |
| float* positions, int count, SkShader* key,SkShader::TileMode tileMode, |
| SkMatrix* matrix, bool blend); |
| SkiaShader* copy(); |
| |
| void describe(ProgramDescription& description, const Extensions& extensions); |
| |
| private: |
| SkiaCircularGradientShader() { |
| } |
| }; // struct SkiaCircularGradientShader |
| |
| /** |
| * A shader that draws two shaders, composited with an xfermode. |
| */ |
| struct SkiaComposeShader: public SkiaShader { |
| ANDROID_API SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode, |
| SkShader* key); |
| ~SkiaComposeShader(); |
| SkiaShader* copy(); |
| |
| void set(TextureCache* textureCache, GradientCache* gradientCache); |
| |
| void describe(ProgramDescription& description, const Extensions& extensions); |
| void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, |
| GLuint* textureUnit); |
| |
| private: |
| SkiaComposeShader(): mCleanup(false) { |
| } |
| |
| void cleanup() { |
| mCleanup = true; |
| } |
| |
| SkiaShader* mFirst; |
| SkiaShader* mSecond; |
| SkXfermode::Mode mMode; |
| |
| bool mCleanup; |
| }; // struct SkiaComposeShader |
| |
| }; // namespace uirenderer |
| }; // namespace android |
| |
| #endif // ANDROID_HWUI_SKIA_SHADER_H |