Merge "Add 3D transforms support to all gradients."
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user