diff options
| -rw-r--r-- | core/jni/android/graphics/Shader.cpp | 91 | ||||
| -rw-r--r-- | graphics/java/android/graphics/RadialGradient.java | 13 | ||||
| -rw-r--r-- | libs/hwui/Matrix.cpp | 6 | ||||
| -rw-r--r-- | libs/hwui/Matrix.h | 2 | ||||
| -rw-r--r-- | libs/hwui/ProgramCache.cpp | 16 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.cpp | 39 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.h | 24 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java | 40 |
8 files changed, 189 insertions, 42 deletions
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index 344669c..ee44747 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -226,10 +226,8 @@ static SkShader* LinearGradient_create2(JNIEnv* env, jobject o, /////////////////////////////////////////////////////////////////////////////////////////////// -static SkShader* RadialGradient_create1(JNIEnv* env, jobject, - float x, float y, float radius, - jintArray colorArray, jfloatArray posArray, int tileMode) -{ +static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius, + jintArray colorArray, jfloatArray posArray, int tileMode) { SkPoint center; center.set(SkFloatToScalar(x), SkFloatToScalar(y)); @@ -259,10 +257,8 @@ static SkShader* RadialGradient_create1(JNIEnv* env, jobject, return shader; } -static SkShader* RadialGradient_create2(JNIEnv* env, jobject, - float x, float y, float radius, - int color0, int color1, int tileMode) -{ +static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius, + int color0, int color1, int tileMode) { SkPoint center; center.set(SkFloatToScalar(x), SkFloatToScalar(y)); @@ -276,11 +272,65 @@ static SkShader* RadialGradient_create2(JNIEnv* env, jobject, return s; } +static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader, + float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) { +#ifdef USE_OPENGL_RENDERER + size_t count = env->GetArrayLength(colorArray); + const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); + + jfloat* storedPositions = new jfloat[count]; + uint32_t* storedColors = new uint32_t[count]; + for (size_t i = 0; i < count; i++) { + storedColors[i] = static_cast<uint32_t>(colorValues[i]); + } + + if (posArray) { + AutoJavaFloatArray autoPos(env, posArray, count); + const float* posValues = autoPos.ptr(); + for (size_t i = 0; i < count; i++) { + storedPositions[i] = posValues[i]; + } + } else { + storedPositions[0] = 0.0f; + storedPositions[1] = 1.0f; + } + + SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors, + storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL, + (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); + + env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); + return skiaShader; +#else + return NULL; +#endif +} + +static SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader, + float x, float y, float radius, int color0, int color1, int tileMode) { +#ifdef USE_OPENGL_RENDERER + float* storedPositions = new float[2]; + storedPositions[0] = 0.0f; + storedPositions[1] = 1.0f; + + uint32_t* storedColors = new uint32_t[2]; + storedColors[0] = static_cast<uint32_t>(color0); + storedColors[1] = static_cast<uint32_t>(color1); + + SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors, + storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL, + (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); + + return skiaShader; +#else + return NULL; +#endif +} + /////////////////////////////////////////////////////////////////////////////// static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y, - jintArray jcolors, jfloatArray jpositions) -{ + jintArray jcolors, jfloatArray jpositions) { size_t count = env->GetArrayLength(jcolors); const jint* colors = env->GetIntArrayElements(jcolors, NULL); @@ -307,8 +357,7 @@ static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y, } static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y, - int color0, int color1) -{ + int color0, int color1) { SkColor colors[2]; colors[0] = color0; colors[1] = color1; @@ -437,22 +486,24 @@ static JNINativeMethod gLinearGradientMethods[] = { }; static JNINativeMethod gRadialGradientMethods[] = { - {"nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 }, - {"nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 } + { "nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 }, + { "nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 }, + { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 }, + { "nativePostCreate2", "(IFFFIII)I", (void*)RadialGradient_postCreate2 } }; static JNINativeMethod gSweepGradientMethods[] = { - {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, - {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }, + { "nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 }, + { "nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }, { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 }, { "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 } }; static JNINativeMethod gComposeShaderMethods[] = { - {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, - {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 }, - {"nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 }, - {"nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 } + { "nativeCreate1", "(III)I", (void*)ComposeShader_create1 }, + { "nativeCreate2", "(III)I", (void*)ComposeShader_create2 }, + { "nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 }, + { "nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 } }; #include <android_runtime/AndroidRuntime.h> diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java index b4e902d..897762c 100644 --- a/graphics/java/android/graphics/RadialGradient.java +++ b/graphics/java/android/graphics/RadialGradient.java @@ -40,6 +40,8 @@ public class RadialGradient extends Shader { throw new IllegalArgumentException("color and position arrays must be of equal length"); } native_instance = nativeCreate1(x, y, radius, colors, positions, tile.nativeInt); + native_shader = nativePostCreate1(native_instance, x, y, radius, colors, positions, + tile.nativeInt); } /** Create a shader that draws a radial gradient given the center and radius. @@ -56,11 +58,18 @@ public class RadialGradient extends Shader { throw new IllegalArgumentException("radius must be > 0"); } native_instance = nativeCreate2(x, y, radius, color0, color1, tile.nativeInt); + native_shader = nativePostCreate2(native_instance, x, y, radius, color0, color1, + tile.nativeInt); } private static native int nativeCreate1(float x, float y, float radius, - int colors[], float positions[], int tileMode); + int colors[], float positions[], int tileMode); private static native int nativeCreate2(float x, float y, float radius, - int color0, int color1, int tileMode); + int color0, int color1, int tileMode); + + private static native int nativePostCreate1(int native_shader, float x, float y, float radius, + int colors[], float positions[], int tileMode); + private static native int nativePostCreate2(int native_shader, float x, float y, float radius, + int color0, int color1, int tileMode); } diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 264ad3d..c698b5a 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -144,6 +144,12 @@ float Matrix4::getTranslateY() { return data[kTranslateY]; } +void Matrix4::multiply(float v) { + for (int i = 0; i < 16; i++) { + data[i] *= v; + } +} + void Matrix4::loadTranslate(float x, float y, float z) { loadIdentity(); data[kTranslateX] = x; diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index c247a67..0608efe 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -83,6 +83,8 @@ public: load(u); } + void multiply(float v); + void translate(float x, float y, float z) { Matrix4 u; u.loadTranslate(x, y, z); diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index bcc1edf..3e9412c 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -40,9 +40,12 @@ const char* gVS_Header_Uniforms_HasGradient[3] = { "uniform vec2 gradientStart;\n" "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 = @@ -56,7 +59,7 @@ const char* gVS_Header_Varyings_HasGradient[3] = { // Linear "varying float index;\n", // Circular - "", + "varying vec2 circular;\n", // Sweep "varying vec2 sweep;\n" }; @@ -69,10 +72,11 @@ const char* gVS_Main_OutGradient[3] = { " vec4 location = screenSpace * position;\n" " index = dot(location.xy - gradientStart, gradient) * gradientLength;\n", // Circular - "", + " vec4 location = screenSpace * position;\n" + " circular = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n", // Sweep " vec4 location = screenSpace * position;\n" - " sweep = location.xy - gradientStart;\n" + " sweep = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n" }; const char* gVS_Main_OutBitmapTexCoords = " vec4 bitmapCoords = textureTransform * position;\n" @@ -98,6 +102,7 @@ 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" @@ -129,7 +134,8 @@ const char* gFS_Main_FetchGradient[3] = { // Linear " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", // Circular - "", + " float index = length(circular) * gradientRadius;\n" + " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", // Sweep " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n" diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index c5d9767..9e1f6c2 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -209,6 +209,30 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo } /////////////////////////////////////////////////////////////////////////////// +// Circular gradient shader +/////////////////////////////////////////////////////////////////////////////// + +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) { +} + +void SkiaCircularGradientShader::describe(ProgramDescription& description, + const Extensions& extensions) { + description.hasGradient = true; + 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 /////////////////////////////////////////////////////////////////////////////// @@ -219,6 +243,13 @@ SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* col mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) { } +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) { +} + SkiaSweepGradientShader::~SkiaSweepGradientShader() { delete[] mColors; delete[] mPositions; @@ -243,10 +274,15 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi float left = mX; float top = mY; + mat4 shaderMatrix; if (mMatrix) { - mat4 shaderMatrix(*mMatrix); + shaderMatrix.load(*mMatrix); shaderMatrix.mapPoint(left, top); } + + mat4 copy(shaderMatrix); + shaderMatrix.loadInverse(copy); + snapshot.transform->mapPoint(left, top); mat4 screenSpace(*snapshot.transform); @@ -255,6 +291,7 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi // 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]); } diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index b67bfee..0023c46 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -152,12 +152,15 @@ struct SkiaSweepGradientShader: public SkiaShader { SkShader* key, SkMatrix* matrix, bool blend); ~SkiaSweepGradientShader(); - void describe(ProgramDescription& description, const Extensions& extensions); - void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, + virtual void describe(ProgramDescription& description, const Extensions& extensions); + virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit); void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); -private: +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; @@ -165,6 +168,21 @@ private: }; // 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); + + void describe(ProgramDescription& description, const Extensions& extensions); + void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, + GLuint* textureUnit); + +private: + float mRadius; +}; // struct SkiaCircularGradientShader + +/** * A shader that draws two shaders, composited with an xfermode. */ struct SkiaComposeShader: public SkiaShader { diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java index e232021..27974e7 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java @@ -42,19 +42,25 @@ public class AdvancedGradientsActivity extends Activity { private final RadialGradient mRadialGradient; private final Matrix mMatrix; private final Matrix mMatrix2; + private final Matrix mMatrix3; GradientsView(Context c) { super(c); - mSweepGradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff); - mRadialGradient = new RadialGradient(100.0f, 100.0f, 100.0f, 0xff000000, 0xffffffff, + mSweepGradient = new SweepGradient(0.0f, 0.0f, 0xff000000, 0xffffffff); + mRadialGradient = new RadialGradient(0.0f, 0.0f, 100.0f, 0xff000000, 0xffffffff, Shader.TileMode.MIRROR); mMatrix = new Matrix(); - mMatrix.setTranslate(50.0f, 50.0f); + mMatrix.setRotate(-45, 0.0f, 0.0f); + mMatrix.postTranslate(100.0f, 100.0f); mMatrix2 = new Matrix(); - mMatrix2.setScale(2.0f, 2.0f); + mMatrix2.setScale(1.0f, 2.0f); + mMatrix2.postRotate(-45, 0.0f, 0.0f); + + mMatrix3 = new Matrix(); + mMatrix3.setTranslate(100.0f, 100.0f); mPaint = new Paint(); } @@ -64,29 +70,41 @@ public class AdvancedGradientsActivity extends Activity { super.onDraw(canvas); canvas.drawRGB(255, 255, 255); - // Bitmap shaders canvas.save(); canvas.translate(130.0f, 100.0f); - mSweepGradient.setLocalMatrix(null); + mSweepGradient.setLocalMatrix(mMatrix3); mPaint.setShader(mSweepGradient); canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); canvas.translate(400.0f, 000.0f); - mPaint.setShader(mRadialGradient); - canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); + mSweepGradient.setLocalMatrix(mMatrix); + mPaint.setShader(mSweepGradient); + canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); canvas.translate(400.0f, 000.0f); - mSweepGradient.setLocalMatrix(mMatrix); + mSweepGradient.setLocalMatrix(mMatrix2); mPaint.setShader(mSweepGradient); canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); canvas.translate(-800.0f, 300.0f); + + mRadialGradient.setLocalMatrix(null); + mPaint.setShader(mRadialGradient); + canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); - mSweepGradient.setLocalMatrix(mMatrix2); - mPaint.setShader(mSweepGradient); + canvas.translate(400.0f, 000.0f); + + mRadialGradient.setLocalMatrix(mMatrix); + mPaint.setShader(mRadialGradient); + canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); + + canvas.translate(400.0f, 000.0f); + + mRadialGradient.setLocalMatrix(mMatrix2); + mPaint.setShader(mRadialGradient); canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint); |
