/* * 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 "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 }; 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 { 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 { 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 { 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 { 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 { 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