| /* | 
 |  * 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 |