diff options
author | Romain Guy <romainguy@google.com> | 2010-10-07 15:07:45 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2010-10-07 15:07:45 -0700 |
commit | 14830948d02f768c41b97b7a8d15e1b3cab78267 (patch) | |
tree | 349cf9a5e1120ca3bc92807efb3db10ff11a8468 | |
parent | 6b7bd24659fb175fe1f0e97c86c18969918b496a (diff) | |
download | frameworks_base-14830948d02f768c41b97b7a8d15e1b3cab78267.zip frameworks_base-14830948d02f768c41b97b7a8d15e1b3cab78267.tar.gz frameworks_base-14830948d02f768c41b97b7a8d15e1b3cab78267.tar.bz2 |
Add 3D transforms support to all gradients.
Change-Id: I61409edd00dab3a11684a3f5e4f7df0afc734758
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 103 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.h | 35 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java | 103 |
4 files changed, 160 insertions, 94 deletions
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index d1a1b45..439e6fb 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -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 = @@ -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" @@ -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" @@ -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" diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 83de2b2..fa85d20 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -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() { @@ -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 /////////////////////////////////////////////////////////////////////////////// @@ -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) { @@ -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); @@ -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]); } @@ -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)++; @@ -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, @@ -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() { @@ -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]); } diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index 2c1eb35..2565e65 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -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); @@ -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 @@ -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; @@ -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); @@ -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; @@ -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 /** diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java index 769bfdd..8fa626b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java @@ -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; @@ -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() { @@ -51,13 +61,29 @@ public class GradientsActivity extends Activity { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - gradientView.setRotationY((float)progress); + 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)); @@ -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; @@ -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; |