Loading libs/hwui/ProgramCache.cpp +3 −10 Original line number Diff line number Diff line Loading @@ -37,12 +37,8 @@ const char* gVS_Header_Uniforms_HasGradient[3] = { // Linear "uniform mat4 screenSpace;\n", // Circular "uniform vec2 gradientStart;\n" "uniform mat4 gradientMatrix;\n" "uniform mat4 screenSpace;\n", // Sweep "uniform vec2 gradientStart;\n" "uniform mat4 gradientMatrix;\n" "uniform mat4 screenSpace;\n" }; const char* gVS_Header_Uniforms_HasBitmap = Loading @@ -68,11 +64,9 @@ const char* gVS_Main_OutGradient[3] = { // Linear " index = (screenSpace * position).x;\n", // Circular " vec4 location = screenSpace * position;\n" " circular = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n", " circular = (screenSpace * position).xy;\n", // Sweep " vec4 location = screenSpace * position;\n" " sweep = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n" " sweep = (screenSpace * position).xy;\n" }; const char* gVS_Main_OutBitmapTexCoords = " vec4 bitmapCoords = textureTransform * position;\n" Loading @@ -98,7 +92,6 @@ const char* gFS_Uniforms_GradientSampler[3] = { // Linear "uniform sampler2D gradientSampler;\n", // Circular "uniform float gradientRadius;\n" "uniform sampler2D gradientSampler;\n", // Sweep "uniform sampler2D gradientSampler;\n" Loading Loading @@ -130,7 +123,7 @@ const char* gFS_Main_FetchGradient[3] = { // Linear " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", // Circular " float index = length(circular) * gradientRadius;\n" " float index = length(circular);\n" " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", // Sweep " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" Loading libs/hwui/SkiaShader.cpp +38 −65 Original line number Diff line number Diff line Loading @@ -49,7 +49,8 @@ static const GLint gTileModes[] = { SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix, bool blend): mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mMatrix(matrix), mBlend(blend) { mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) { setMatrix(matrix); } SkiaShader::~SkiaShader() { Loading @@ -69,6 +70,11 @@ void SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); } void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix); screenSpace.multiply(modelView); } /////////////////////////////////////////////////////////////////////////////// // Bitmap shader /////////////////////////////////////////////////////////////////////////////// Loading @@ -76,6 +82,7 @@ void SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint SkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix, bool blend): SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) { updateLocalMatrix(matrix); } void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) { Loading Loading @@ -116,14 +123,7 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, const float height = texture->height; mat4 textureTransform; if (mMatrix) { SkMatrix inverse; mMatrix->invert(&inverse); textureTransform.load(inverse); textureTransform.multiply(modelView); } else { textureTransform.load(modelView); } computeScreenSpaceMatrix(textureTransform, modelView); // Uniforms bindTexture(texture->id, mWrapS, mWrapT, textureSlot); Loading @@ -136,15 +136,7 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, void SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot) { mat4 textureTransform; if (mMatrix) { SkMatrix inverse; mMatrix->invert(&inverse); textureTransform.load(inverse); textureTransform.multiply(modelView); } else { textureTransform.load(modelView); } computeScreenSpaceMatrix(textureTransform, modelView); glUniformMatrix4fv(program->getUniform("textureTransform"), 1, GL_FALSE, &textureTransform.data[0]); } Loading Loading @@ -192,23 +184,6 @@ void SkiaLinearGradientShader::describe(ProgramDescription& description, description.gradientType = ProgramDescription::kGradientLinear; } void SkiaLinearGradientShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix); screenSpace.multiply(modelView); } void SkiaLinearGradientShader::updateLocalMatrix(const SkMatrix* matrix) { if (matrix) { mat4 localMatrix(*matrix); mShaderMatrix.loadInverse(localMatrix); } } void SkiaLinearGradientShader::setMatrix(SkMatrix* matrix) { SkiaShader::setMatrix(matrix); updateLocalMatrix(matrix); } void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit) { GLuint textureSlot = (*textureUnit)++; Loading Loading @@ -239,12 +214,23 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo // Circular gradient shader /////////////////////////////////////////////////////////////////////////////// static void toCircularUnitMatrix(const float x, const float y, const float radius, SkMatrix* matrix) { const float inv = 1.0f / radius; matrix->setTranslate(-x, -y); matrix->postScale(inv, inv); } SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend): SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key, tileMode, matrix, blend), mRadius(radius) { tileMode, matrix, blend) { SkMatrix unitMatrix; toCircularUnitMatrix(x, y, radius, &unitMatrix); mUnitMatrix.load(unitMatrix); updateLocalMatrix(matrix); } void SkiaCircularGradientShader::describe(ProgramDescription& description, Loading @@ -253,28 +239,31 @@ void SkiaCircularGradientShader::describe(ProgramDescription& description, description.gradientType = ProgramDescription::kGradientCircular; } void SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit) { SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit); glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius); } /////////////////////////////////////////////////////////////////////////////// // Sweep gradient shader /////////////////////////////////////////////////////////////////////////////// static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) { matrix->setTranslate(-x, -y); } SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend): SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, matrix, blend), mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) { mColors(colors), mPositions(positions), mCount(count) { SkMatrix unitMatrix; toSweepUnitMatrix(x, y, &unitMatrix); mUnitMatrix.load(unitMatrix); updateLocalMatrix(matrix); } SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend): SkiaShader(type, key, tileMode, tileMode, matrix, blend), mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) { mColors(colors), mPositions(positions), mCount(count) { } SkiaSweepGradientShader::~SkiaSweepGradientShader() { Loading @@ -298,35 +287,19 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount); } float left = mX; float top = mY; mat4 shaderMatrix; if (mMatrix) { shaderMatrix.load(*mMatrix); shaderMatrix.mapPoint(left, top); } mat4 copy(shaderMatrix); shaderMatrix.loadInverse(copy); snapshot.transform->mapPoint(left, top); mat4 screenSpace(*snapshot.transform); screenSpace.multiply(modelView); mat4 screenSpace; computeScreenSpaceMatrix(screenSpace, modelView); // Uniforms bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot); glUniform1i(program->getUniform("gradientSampler"), textureSlot); glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]); glUniform2f(program->getUniform("gradientStart"), left, top); glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); } void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot) { mat4 screenSpace(*snapshot.transform); screenSpace.multiply(modelView); mat4 screenSpace; computeScreenSpaceMatrix(screenSpace, modelView); glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); } Loading libs/hwui/SkiaShader.h +17 −18 Original line number Diff line number Diff line Loading @@ -77,10 +77,21 @@ struct SkiaShader { const Snapshot& snapshot) { } virtual void setMatrix(SkMatrix* matrix) { mMatrix = matrix; void setMatrix(SkMatrix* matrix) { updateLocalMatrix(matrix); } void updateLocalMatrix(const SkMatrix* matrix) { if (matrix) { mat4 localMatrix(*matrix); mShaderMatrix.loadInverse(localMatrix); } else { mShaderMatrix.loadIdentity(); } } void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView); protected: inline void bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit); Loading @@ -88,11 +99,13 @@ protected: SkShader* mKey; SkShader::TileMode mTileX; SkShader::TileMode mTileY; SkMatrix* mMatrix; bool mBlend; TextureCache* mTextureCache; GradientCache* mGradientCache; mat4 mUnitMatrix; mat4 mShaderMatrix; }; // struct SkiaShader Loading Loading @@ -139,15 +152,7 @@ struct SkiaLinearGradientShader: public SkiaShader { GLuint* textureUnit); void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); void setMatrix(SkMatrix* matrix); private: void updateLocalMatrix(const SkMatrix* matrix); void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView); mat4 mUnitMatrix; mat4 mShaderMatrix; float* mBounds; uint32_t* mColors; float* mPositions; Loading @@ -163,7 +168,7 @@ struct SkiaSweepGradientShader: public SkiaShader { ~SkiaSweepGradientShader(); virtual void describe(ProgramDescription& description, const Extensions& extensions); virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit); void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); Loading @@ -171,7 +176,6 @@ protected: SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); float mX, mY; uint32_t* mColors; float* mPositions; int mCount; Loading @@ -185,11 +189,6 @@ struct SkiaCircularGradientShader: public SkiaSweepGradientShader { int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); void describe(ProgramDescription& description, const Extensions& extensions); void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit); private: float mRadius; }; // struct SkiaCircularGradientShader /** Loading tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java +102 −1 Original line number Diff line number Diff line Loading @@ -18,11 +18,16 @@ package com.android.test.hwui; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.RadialGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Shader; import android.graphics.SweepGradient; import android.os.Bundle; import android.view.Gravity; import android.view.View; Loading @@ -36,8 +41,13 @@ public class GradientsActivity extends Activity { super.onCreate(savedInstanceState); final FrameLayout layout = new FrameLayout(this); final ShadersView shadersView = new ShadersView(this); final GradientView gradientView = new GradientView(this); final RadialGradientView radialGradientView = new RadialGradientView(this); final SweepGradientView sweepGradientView = new SweepGradientView(this); final BitmapView bitmapView = new BitmapView(this); final SeekBar rotateView = new SeekBar(this); rotateView.setMax(360); rotateView.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { Loading @@ -52,12 +62,28 @@ public class GradientsActivity extends Activity { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { gradientView.setRotationY((float) progress); radialGradientView.setRotationX((float) progress); sweepGradientView.setRotationY((float) progress); bitmapView.setRotationX((float) progress); } }); layout.addView(shadersView); layout.addView(gradientView, new FrameLayout.LayoutParams( 200, 200, Gravity.CENTER)); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER); lp.setMargins(220, 0, 0, 0); layout.addView(radialGradientView, lp); lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER); lp.setMargins(440, 0, 0, 0); layout.addView(sweepGradientView, lp); lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER); lp.setMargins(220, -220, 0, 0); layout.addView(bitmapView, lp); layout.addView(rotateView, new FrameLayout.LayoutParams( 300, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); Loading @@ -65,6 +91,32 @@ public class GradientsActivity extends Activity { setContentView(layout); } static class BitmapView extends View { private final Paint mPaint; BitmapView(Context c) { super(c); Bitmap texture = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1); BitmapShader shader = new BitmapShader(texture, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaint = new Paint(); mPaint.setShader(shader); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(200, 200); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint); } } static class GradientView extends View { private final Paint mPaint; Loading @@ -90,6 +142,55 @@ public class GradientsActivity extends Activity { } } static class RadialGradientView extends View { private final Paint mPaint; RadialGradientView(Context c) { super(c); RadialGradient gradient = new RadialGradient(0.0f, 0.0f, 100.0f, 0xff000000, 0xffffffff, Shader.TileMode.MIRROR); mPaint = new Paint(); mPaint.setShader(gradient); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(200, 200); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint); } } static class SweepGradientView extends View { private final Paint mPaint; SweepGradientView(Context c) { super(c); SweepGradient gradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff); mPaint = new Paint(); mPaint.setShader(gradient); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(200, 200); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint); } } static class ShadersView extends View { private final Paint mPaint; private final float mDrawWidth; Loading Loading
libs/hwui/ProgramCache.cpp +3 −10 Original line number Diff line number Diff line Loading @@ -37,12 +37,8 @@ const char* gVS_Header_Uniforms_HasGradient[3] = { // Linear "uniform mat4 screenSpace;\n", // Circular "uniform vec2 gradientStart;\n" "uniform mat4 gradientMatrix;\n" "uniform mat4 screenSpace;\n", // Sweep "uniform vec2 gradientStart;\n" "uniform mat4 gradientMatrix;\n" "uniform mat4 screenSpace;\n" }; const char* gVS_Header_Uniforms_HasBitmap = Loading @@ -68,11 +64,9 @@ const char* gVS_Main_OutGradient[3] = { // Linear " index = (screenSpace * position).x;\n", // Circular " vec4 location = screenSpace * position;\n" " circular = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n", " circular = (screenSpace * position).xy;\n", // Sweep " vec4 location = screenSpace * position;\n" " sweep = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n" " sweep = (screenSpace * position).xy;\n" }; const char* gVS_Main_OutBitmapTexCoords = " vec4 bitmapCoords = textureTransform * position;\n" Loading @@ -98,7 +92,6 @@ const char* gFS_Uniforms_GradientSampler[3] = { // Linear "uniform sampler2D gradientSampler;\n", // Circular "uniform float gradientRadius;\n" "uniform sampler2D gradientSampler;\n", // Sweep "uniform sampler2D gradientSampler;\n" Loading Loading @@ -130,7 +123,7 @@ const char* gFS_Main_FetchGradient[3] = { // Linear " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", // Circular " float index = length(circular) * gradientRadius;\n" " float index = length(circular);\n" " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", // Sweep " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" Loading
libs/hwui/SkiaShader.cpp +38 −65 Original line number Diff line number Diff line Loading @@ -49,7 +49,8 @@ static const GLint gTileModes[] = { SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix, bool blend): mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mMatrix(matrix), mBlend(blend) { mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) { setMatrix(matrix); } SkiaShader::~SkiaShader() { Loading @@ -69,6 +70,11 @@ void SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); } void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix); screenSpace.multiply(modelView); } /////////////////////////////////////////////////////////////////////////////// // Bitmap shader /////////////////////////////////////////////////////////////////////////////// Loading @@ -76,6 +82,7 @@ void SkiaShader::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint SkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix, bool blend): SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) { updateLocalMatrix(matrix); } void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) { Loading Loading @@ -116,14 +123,7 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, const float height = texture->height; mat4 textureTransform; if (mMatrix) { SkMatrix inverse; mMatrix->invert(&inverse); textureTransform.load(inverse); textureTransform.multiply(modelView); } else { textureTransform.load(modelView); } computeScreenSpaceMatrix(textureTransform, modelView); // Uniforms bindTexture(texture->id, mWrapS, mWrapT, textureSlot); Loading @@ -136,15 +136,7 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, void SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot) { mat4 textureTransform; if (mMatrix) { SkMatrix inverse; mMatrix->invert(&inverse); textureTransform.load(inverse); textureTransform.multiply(modelView); } else { textureTransform.load(modelView); } computeScreenSpaceMatrix(textureTransform, modelView); glUniformMatrix4fv(program->getUniform("textureTransform"), 1, GL_FALSE, &textureTransform.data[0]); } Loading Loading @@ -192,23 +184,6 @@ void SkiaLinearGradientShader::describe(ProgramDescription& description, description.gradientType = ProgramDescription::kGradientLinear; } void SkiaLinearGradientShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix); screenSpace.multiply(modelView); } void SkiaLinearGradientShader::updateLocalMatrix(const SkMatrix* matrix) { if (matrix) { mat4 localMatrix(*matrix); mShaderMatrix.loadInverse(localMatrix); } } void SkiaLinearGradientShader::setMatrix(SkMatrix* matrix) { SkiaShader::setMatrix(matrix); updateLocalMatrix(matrix); } void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit) { GLuint textureSlot = (*textureUnit)++; Loading Loading @@ -239,12 +214,23 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo // Circular gradient shader /////////////////////////////////////////////////////////////////////////////// static void toCircularUnitMatrix(const float x, const float y, const float radius, SkMatrix* matrix) { const float inv = 1.0f / radius; matrix->setTranslate(-x, -y); matrix->postScale(inv, inv); } SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend): SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key, tileMode, matrix, blend), mRadius(radius) { tileMode, matrix, blend) { SkMatrix unitMatrix; toCircularUnitMatrix(x, y, radius, &unitMatrix); mUnitMatrix.load(unitMatrix); updateLocalMatrix(matrix); } void SkiaCircularGradientShader::describe(ProgramDescription& description, Loading @@ -253,28 +239,31 @@ void SkiaCircularGradientShader::describe(ProgramDescription& description, description.gradientType = ProgramDescription::kGradientCircular; } void SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit) { SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit); glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius); } /////////////////////////////////////////////////////////////////////////////// // Sweep gradient shader /////////////////////////////////////////////////////////////////////////////// static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) { matrix->setTranslate(-x, -y); } SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend): SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, matrix, blend), mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) { mColors(colors), mPositions(positions), mCount(count) { SkMatrix unitMatrix; toSweepUnitMatrix(x, y, &unitMatrix); mUnitMatrix.load(unitMatrix); updateLocalMatrix(matrix); } SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend): SkiaShader(type, key, tileMode, tileMode, matrix, blend), mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) { mColors(colors), mPositions(positions), mCount(count) { } SkiaSweepGradientShader::~SkiaSweepGradientShader() { Loading @@ -298,35 +287,19 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount); } float left = mX; float top = mY; mat4 shaderMatrix; if (mMatrix) { shaderMatrix.load(*mMatrix); shaderMatrix.mapPoint(left, top); } mat4 copy(shaderMatrix); shaderMatrix.loadInverse(copy); snapshot.transform->mapPoint(left, top); mat4 screenSpace(*snapshot.transform); screenSpace.multiply(modelView); mat4 screenSpace; computeScreenSpaceMatrix(screenSpace, modelView); // Uniforms bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot); glUniform1i(program->getUniform("gradientSampler"), textureSlot); glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]); glUniform2f(program->getUniform("gradientStart"), left, top); glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); } void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot) { mat4 screenSpace(*snapshot.transform); screenSpace.multiply(modelView); mat4 screenSpace; computeScreenSpaceMatrix(screenSpace, modelView); glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); } Loading
libs/hwui/SkiaShader.h +17 −18 Original line number Diff line number Diff line Loading @@ -77,10 +77,21 @@ struct SkiaShader { const Snapshot& snapshot) { } virtual void setMatrix(SkMatrix* matrix) { mMatrix = matrix; void setMatrix(SkMatrix* matrix) { updateLocalMatrix(matrix); } void updateLocalMatrix(const SkMatrix* matrix) { if (matrix) { mat4 localMatrix(*matrix); mShaderMatrix.loadInverse(localMatrix); } else { mShaderMatrix.loadIdentity(); } } void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView); protected: inline void bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit); Loading @@ -88,11 +99,13 @@ protected: SkShader* mKey; SkShader::TileMode mTileX; SkShader::TileMode mTileY; SkMatrix* mMatrix; bool mBlend; TextureCache* mTextureCache; GradientCache* mGradientCache; mat4 mUnitMatrix; mat4 mShaderMatrix; }; // struct SkiaShader Loading Loading @@ -139,15 +152,7 @@ struct SkiaLinearGradientShader: public SkiaShader { GLuint* textureUnit); void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); void setMatrix(SkMatrix* matrix); private: void updateLocalMatrix(const SkMatrix* matrix); void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView); mat4 mUnitMatrix; mat4 mShaderMatrix; float* mBounds; uint32_t* mColors; float* mPositions; Loading @@ -163,7 +168,7 @@ struct SkiaSweepGradientShader: public SkiaShader { ~SkiaSweepGradientShader(); virtual void describe(ProgramDescription& description, const Extensions& extensions); virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit); void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); Loading @@ -171,7 +176,6 @@ protected: SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); float mX, mY; uint32_t* mColors; float* mPositions; int mCount; Loading @@ -185,11 +189,6 @@ struct SkiaCircularGradientShader: public SkiaSweepGradientShader { int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); void describe(ProgramDescription& description, const Extensions& extensions); void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit); private: float mRadius; }; // struct SkiaCircularGradientShader /** Loading
tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java +102 −1 Original line number Diff line number Diff line Loading @@ -18,11 +18,16 @@ package com.android.test.hwui; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.RadialGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Shader; import android.graphics.SweepGradient; import android.os.Bundle; import android.view.Gravity; import android.view.View; Loading @@ -36,8 +41,13 @@ public class GradientsActivity extends Activity { super.onCreate(savedInstanceState); final FrameLayout layout = new FrameLayout(this); final ShadersView shadersView = new ShadersView(this); final GradientView gradientView = new GradientView(this); final RadialGradientView radialGradientView = new RadialGradientView(this); final SweepGradientView sweepGradientView = new SweepGradientView(this); final BitmapView bitmapView = new BitmapView(this); final SeekBar rotateView = new SeekBar(this); rotateView.setMax(360); rotateView.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { Loading @@ -52,12 +62,28 @@ public class GradientsActivity extends Activity { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { gradientView.setRotationY((float) progress); radialGradientView.setRotationX((float) progress); sweepGradientView.setRotationY((float) progress); bitmapView.setRotationX((float) progress); } }); layout.addView(shadersView); layout.addView(gradientView, new FrameLayout.LayoutParams( 200, 200, Gravity.CENTER)); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER); lp.setMargins(220, 0, 0, 0); layout.addView(radialGradientView, lp); lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER); lp.setMargins(440, 0, 0, 0); layout.addView(sweepGradientView, lp); lp = new FrameLayout.LayoutParams(200, 200, Gravity.CENTER); lp.setMargins(220, -220, 0, 0); layout.addView(bitmapView, lp); layout.addView(rotateView, new FrameLayout.LayoutParams( 300, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); Loading @@ -65,6 +91,32 @@ public class GradientsActivity extends Activity { setContentView(layout); } static class BitmapView extends View { private final Paint mPaint; BitmapView(Context c) { super(c); Bitmap texture = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1); BitmapShader shader = new BitmapShader(texture, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaint = new Paint(); mPaint.setShader(shader); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(200, 200); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint); } } static class GradientView extends View { private final Paint mPaint; Loading @@ -90,6 +142,55 @@ public class GradientsActivity extends Activity { } } static class RadialGradientView extends View { private final Paint mPaint; RadialGradientView(Context c) { super(c); RadialGradient gradient = new RadialGradient(0.0f, 0.0f, 100.0f, 0xff000000, 0xffffffff, Shader.TileMode.MIRROR); mPaint = new Paint(); mPaint.setShader(gradient); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(200, 200); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint); } } static class SweepGradientView extends View { private final Paint mPaint; SweepGradientView(Context c) { super(c); SweepGradient gradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff); mPaint = new Paint(); mPaint.setShader(gradient); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(200, 200); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint); } } static class ShadersView extends View { private final Paint mPaint; private final float mDrawWidth; Loading