summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeon Scroggins III <scroggo@google.com>2014-05-05 12:50:38 -0400
committerLeon Scroggins III <scroggo@google.com>2014-05-22 14:46:59 -0400
commitd1ad5e62fda248c6d185cde3cb6d9f01a223066c (patch)
tree6e2dcdaaab6c38f46f36b944f9c4212c485ff3e2
parent951ecb77c5dfe69a4d19d26429286111333ab123 (diff)
downloadframeworks_base-d1ad5e62fda248c6d185cde3cb6d9f01a223066c.zip
frameworks_base-d1ad5e62fda248c6d185cde3cb6d9f01a223066c.tar.gz
frameworks_base-d1ad5e62fda248c6d185cde3cb6d9f01a223066c.tar.bz2
Inspect SkShader to determine hw shader.
Instead of duplicating internal info about SkShader, inspect the SkShader installed on the SkPaint. core/java/android/view/GLES20Canvas.java: Remove setupModifiers, nResetModifiers, and nSetupShader. core/jni/android/graphics/Shader.cpp: Remove calls to create/destroy the (previously) attached SkiaShader. core/jni/android_view_GLES20Canvas.cpp: Remove native code for setupShader and resetModifiers. graphics/java/android/graphics/BitmapShader.java: graphics/java/android/graphics/ComposeShader.java: graphics/java/android/graphics/LinearGradient.java: graphics/java/android/graphics/RadialGradient.java: graphics/java/android/graphics/Shader.java: graphics/java/android/graphics/SweepGradient.java: Remove code keeping track of native SkiaShader. libs/hwui/Caches.h: Include Extensions.h. libs/hwui/DeferredDisplayList.cpp: Compare shaders on the paint, instead of on DrawModifiers. libs/hwui/DisplayList.cpp: libs/hwui/DisplayList.h: Remove vector of SkiaShaders. libs/hwui/DisplayListOp.h: Access the SkShader on mPaint. Remove SetupShaderOp and ResetShaderOp. libs/hwui/DisplayListRenderer.cpp: libs/hwui/DisplayListRenderer.h: Remove resetShader, setupShader, refShader, and mShaderMap. libs/hwui/FontRenderer.cpp: Pass SkShader to setupDrawShader and setupDrawShaderUniforms. libs/hwui/OpenGLRenderer.cpp: libs/hwui/OpenGLRenderer.h: Add LayerShader, a class inheriting from SkShader, to mimic the behavior of SkiaLayerShader. Unlike SkiaLayerShader, it can be set on the SkPaint so it can be inspected later. Set a LayerShader instead of a SkiaLayerShader. setupDrawShader and setupDrawShaderUniforms now inspect an SkShader passed in. Inspect SkShader instead of mDrawModifiers.mShader. Remove resetShader and setupShader. setupDrawColorUniforms now takes a boolean indicating whether there is a shader. Add an inline function for accessing the SkShader on an SkPaint. In setupDrawBlending(Layer*, bool), do not check the shader (which will never be set), but do check whether the color filter may change the alpha (newly fixed behavior). In setupDrawBlending(SkPaint, ...), check the SkShader and whether the color filter affects alpha (the latter is new behavior). libs/hwui/Renderer.h: Remove pure virtual functions setupShader and resetShader. libs/hwui/ResourceCache.cpp: libs/hwui/ResourceCache.h: Remove functions for refing/unrefing shaders. libs/hwui/SkiaShader.cpp: libs/hwui/SkiaShader.h: Much of this code was redundant and has been removed. Convert structs into class with nothing but static functions for calling describe/setupProgram. libs/hwui/TextureCache.cpp: libs/hwui/TextureCache.h: Use the SkPixelRef as the key to the bitmap Lru cache, since shader inspection will provide a different SkBitmap pointer (though it will hold the correct SkPixelRef with the correct generation ID). tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java: tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java: Update manual test to have more shaders: radial, sweep, compose, invalid compose. BUG:10650594 Change-Id: Iaa7189178bda1c55f96da044d2a9fa602ba36034
-rw-r--r--core/java/android/view/GLES20Canvas.java355
-rw-r--r--core/jni/android/graphics/Shader.cpp297
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp24
-rw-r--r--graphics/java/android/graphics/BitmapShader.java3
-rw-r--r--graphics/java/android/graphics/ComposeShader.java14
-rw-r--r--graphics/java/android/graphics/LinearGradient.java8
-rw-r--r--graphics/java/android/graphics/RadialGradient.java9
-rw-r--r--graphics/java/android/graphics/Shader.java12
-rw-r--r--graphics/java/android/graphics/SweepGradient.java7
-rw-r--r--libs/hwui/Caches.h1
-rw-r--r--libs/hwui/DeferredDisplayList.cpp6
-rw-r--r--libs/hwui/DisplayList.cpp6
-rw-r--r--libs/hwui/DisplayList.h2
-rw-r--r--libs/hwui/DisplayListOp.h44
-rw-r--r--libs/hwui/DisplayListRenderer.cpp10
-rw-r--r--libs/hwui/DisplayListRenderer.h19
-rw-r--r--libs/hwui/FontRenderer.cpp4
-rw-r--r--libs/hwui/OpenGLRenderer.cpp156
-rw-r--r--libs/hwui/OpenGLRenderer.h32
-rw-r--r--libs/hwui/Renderer.h4
-rw-r--r--libs/hwui/ResourceCache.cpp44
-rw-r--r--libs/hwui/ResourceCache.h8
-rw-r--r--libs/hwui/SkiaShader.cpp570
-rw-r--r--libs/hwui/SkiaShader.h269
-rw-r--r--libs/hwui/TextureCache.cpp16
-rw-r--r--libs/hwui/TextureCache.h6
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java30
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java25
28 files changed, 644 insertions, 1337 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index a272296..424d860 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -41,10 +41,6 @@ import android.text.TextUtils;
* An implementation of Canvas on top of OpenGL ES 2.0.
*/
class GLES20Canvas extends HardwareCanvas {
- // Must match modifiers used in the JNI layer
- private static final int MODIFIER_NONE = 0;
- private static final int MODIFIER_SHADER = 2;
-
private final boolean mOpaque;
protected long mRenderer;
@@ -650,13 +646,8 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
- startAngle, sweepAngle, useCenter, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
+ startAngle, sweepAngle, useCenter, paint.mNativePaint);
}
private static native void nDrawArc(long renderer, float left, float top,
@@ -672,7 +663,6 @@ class GLES20Canvas extends HardwareCanvas {
public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing patches
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
@@ -682,7 +672,6 @@ class GLES20Canvas extends HardwareCanvas {
public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing patches
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
@@ -694,14 +683,8 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
}
private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
@@ -710,15 +693,9 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
- matrix.native_instance, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
+ matrix.native_instance, nativePaint);
}
private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
@@ -727,55 +704,43 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
-
- int left, top, right, bottom;
- if (src == null) {
- left = top = 0;
- right = bitmap.getWidth();
- bottom = bitmap.getHeight();
- } else {
- left = src.left;
- right = src.right;
- top = src.top;
- bottom = src.bottom;
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ int left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
}
+
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
@Override
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
-
- float left, top, right, bottom;
- if (src == null) {
- left = top = 0;
- right = bitmap.getWidth();
- bottom = bitmap.getHeight();
- } else {
- left = src.left;
- right = src.right;
- top = src.top;
- bottom = src.bottom;
- }
-
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+
+ float left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
}
+
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
@@ -805,7 +770,6 @@ class GLES20Canvas extends HardwareCanvas {
throw new ArrayIndexOutOfBoundsException();
}
- // Shaders are ignored when drawing bitmaps
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawBitmap(mRenderer, colors, offset, stride, x, y,
width, height, hasAlpha, nativePaint);
@@ -817,7 +781,6 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
int width, int height, boolean hasAlpha, Paint paint) {
- // Shaders are ignored when drawing bitmaps
drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
}
@@ -840,14 +803,9 @@ class GLES20Canvas extends HardwareCanvas {
checkRange(colors.length, colorOffset, count);
}
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
- verts, vertOffset, colors, colorOffset, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
+ verts, vertOffset, colors, colorOffset, nativePaint);
}
private static native void nDrawBitmapMesh(long renderer, long bitmap, byte[] buffer,
@@ -856,12 +814,7 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawCircle(float cx, float cy, float radius, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
}
private static native void nDrawCircle(long renderer, float cx, float cy,
@@ -906,12 +859,7 @@ class GLES20Canvas extends HardwareCanvas {
if ((offset | count) < 0 || offset + count > pts.length) {
throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
}
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
}
private static native void nDrawLines(long renderer, float[] points,
@@ -924,12 +872,7 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawOval(RectF oval, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
}
private static native void nDrawOval(long renderer, float left, float top,
@@ -944,17 +887,12 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawPath(Path path, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- if (path.isSimplePath) {
- if (path.rects != null) {
- nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
- }
- } else {
- nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
+ if (path.isSimplePath) {
+ if (path.rects != null) {
+ nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
}
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ } else {
+ nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
}
}
@@ -962,12 +900,7 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nDrawRects(long renderer, long region, long paint);
void drawRects(float[] rects, int count, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawRects(mRenderer, rects, count, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawRects(mRenderer, rects, count, paint.mNativePaint);
}
private static native void nDrawRects(long renderer, float[] rects, int count, long paint);
@@ -1029,12 +962,7 @@ class GLES20Canvas extends HardwareCanvas {
public void drawPoints(float[] pts, int offset, int count, Paint paint) {
if (count < 2) return;
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
}
private static native void nDrawPoints(long renderer, float[] points,
@@ -1047,12 +975,7 @@ class GLES20Canvas extends HardwareCanvas {
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
}
private static native void nDrawPosText(long renderer, char[] text, int index, int count,
@@ -1065,12 +988,7 @@ class GLES20Canvas extends HardwareCanvas {
throw new ArrayIndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
}
private static native void nDrawPosText(long renderer, String text, int start, int end,
@@ -1079,12 +997,7 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawRect(float left, float top, float right, float bottom, Paint paint) {
if (left == right || top == bottom) return;
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
}
private static native void nDrawRect(long renderer, float left, float top,
@@ -1108,12 +1021,7 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
}
private static native void nDrawRoundRect(long renderer, float left, float top,
@@ -1125,13 +1033,8 @@ class GLES20Canvas extends HardwareCanvas {
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint,
- paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawText(mRenderer, text, index, count, x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
private static native void nDrawText(long renderer, char[] text, int index, int count,
@@ -1139,24 +1042,18 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
- int modifiers = setupModifiers(paint);
- try {
- if (text instanceof String || text instanceof SpannedString ||
- text instanceof SpannableString) {
- nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
- paint.mNativePaint, paint.mNativeTypeface);
- } else if (text instanceof GraphicsOperations) {
- ((GraphicsOperations) text).drawText(this, start, end, x, y,
- paint);
- } else {
- char[] buf = TemporaryBuffer.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- nDrawText(mRenderer, buf, 0, end - start, x, y,
- paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
- TemporaryBuffer.recycle(buf);
- }
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
+ paint.mNativePaint, paint.mNativeTypeface);
+ } else if (text instanceof GraphicsOperations) {
+ ((GraphicsOperations) text).drawText(this, start, end, x, y, paint);
+ } else {
+ char[] buf = TemporaryBuffer.obtain(end - start);
+ TextUtils.getChars(text, start, end, buf, 0);
+ nDrawText(mRenderer, buf, 0, end - start, x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
}
}
@@ -1166,13 +1063,8 @@ class GLES20Canvas extends HardwareCanvas {
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint,
- paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawText(mRenderer, text, start, end, x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
private static native void nDrawText(long renderer, String text, int start, int end,
@@ -1180,13 +1072,8 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public void drawText(String text, float x, float y, Paint paint) {
- int modifiers = setupModifiers(paint);
- try {
- nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
- paint.mNativePaint, paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawText(mRenderer, text, 0, text.length(), x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
@Override
@@ -1196,13 +1083,8 @@ class GLES20Canvas extends HardwareCanvas {
throw new ArrayIndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
+ paint.mBidiFlags, paint.mNativePaint);
}
private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
@@ -1212,13 +1094,8 @@ class GLES20Canvas extends HardwareCanvas {
public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
if (text.length() == 0) return;
- int modifiers = setupModifiers(paint);
- try {
- nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
+ paint.mBidiFlags, paint.mNativePaint);
}
private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
@@ -1234,13 +1111,8 @@ class GLES20Canvas extends HardwareCanvas {
throw new IllegalArgumentException("Unknown direction: " + dir);
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
- paint.mNativePaint, paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
+ paint.mNativePaint, paint.mNativeTypeface);
}
private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
@@ -1253,27 +1125,22 @@ class GLES20Canvas extends HardwareCanvas {
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- int flags = dir == 0 ? 0 : 1;
- if (text instanceof String || text instanceof SpannedString ||
- text instanceof SpannableString) {
- nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
- contextEnd, x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
- } else if (text instanceof GraphicsOperations) {
- ((GraphicsOperations) text).drawTextRun(this, start, end,
- contextStart, contextEnd, x, y, flags, paint);
- } else {
- int contextLen = contextEnd - contextStart;
- int len = end - start;
- char[] buf = TemporaryBuffer.obtain(contextLen);
- TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
- nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
- x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
- TemporaryBuffer.recycle(buf);
- }
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ int flags = dir == 0 ? 0 : 1;
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
+ contextEnd, x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
+ } else if (text instanceof GraphicsOperations) {
+ ((GraphicsOperations) text).drawTextRun(this, start, end,
+ contextStart, contextEnd, x, y, flags, paint);
+ } else {
+ int contextLen = contextEnd - contextStart;
+ int len = end - start;
+ char[] buf = TemporaryBuffer.obtain(contextLen);
+ TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+ nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
+ x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
}
}
@@ -1286,40 +1153,4 @@ class GLES20Canvas extends HardwareCanvas {
int indexOffset, int indexCount, Paint paint) {
// TODO: Implement
}
-
- private int setupModifiers(Bitmap b, Paint paint) {
- if (b.getConfig() != Bitmap.Config.ALPHA_8) {
- return MODIFIER_NONE;
- } else {
- return setupModifiers(paint);
- }
- }
-
- private int setupModifiers(Paint paint) {
- int modifiers = MODIFIER_NONE;
-
- final Shader shader = paint.getShader();
- if (shader != null) {
- nSetupShader(mRenderer, shader.native_shader);
- modifiers |= MODIFIER_SHADER;
- }
-
- return modifiers;
- }
-
- private int setupModifiers(Paint paint, int flags) {
- int modifiers = MODIFIER_NONE;
-
- final Shader shader = paint.getShader();
- if (shader != null && (flags & MODIFIER_SHADER) != 0) {
- nSetupShader(mRenderer, shader.native_shader);
- modifiers |= MODIFIER_SHADER;
- }
-
- return modifiers;
- }
-
- private static native void nSetupShader(long renderer, long shader);
-
- private static native void nResetModifiers(long renderer, int modifiers);
}
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b389d9e..0cfcaef 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -50,26 +50,16 @@ static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvAr
///////////////////////////////////////////////////////////////////////////////////////////////
-static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong skiaShaderHandle)
+static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle)
{
SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- SkiaShader* skiaShader = reinterpret_cast<SkiaShader*>(skiaShaderHandle);
SkSafeUnref(shader);
- // skiaShader == NULL when not !USE_OPENGL_RENDERER, so no need to delete it outside the ifdef
-#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader);
- } else {
- delete skiaShader;
- }
-#endif
}
static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong skiaShaderHandle, jlong matrixHandle)
+ jlong matrixHandle)
{
SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- SkiaShader* skiaShader = reinterpret_cast<SkiaShader*>(skiaShaderHandle);
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
if (shader) {
if (NULL == matrix) {
@@ -78,9 +68,6 @@ static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle,
else {
shader->setLocalMatrix(*matrix);
}
-#ifdef USE_OPENGL_RENDERER
- skiaShader->setMatrix(const_cast<SkMatrix*>(matrix));
-#endif
}
}
@@ -98,20 +85,6 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle
return reinterpret_cast<jlong>(s);
}
-static jlong BitmapShader_postConstructor(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong bitmapHandle, jint tileModeX, jint tileModeY) {
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-#ifdef USE_OPENGL_RENDERER
- SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader,
- static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY),
- NULL, !shader->isOpaque());
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong LinearGradient_create1(JNIEnv* env, jobject o,
@@ -141,105 +114,6 @@ static jlong LinearGradient_create1(JNIEnv* env, jobject o,
return reinterpret_cast<jlong>(shader);
}
-static jlong LinearGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x0, jfloat y0, jfloat x1, jfloat y1, jintArray colorArray,
- jfloatArray posArray, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- size_t count = env->GetArrayLength(colorArray);
- const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
-
- jfloat* storedBounds = new jfloat[4];
- storedBounds[0] = x0; storedBounds[1] = y0;
- storedBounds[2] = x1; storedBounds[3] = y1;
-
- bool missFirst = false;
- bool missLast = false;
- size_t stopCount = count;
-
- jfloat* storedPositions = NULL;
- if (posArray) {
- AutoJavaFloatArray autoPos(env, posArray, count);
- const float* posValues = autoPos.ptr();
-
- missFirst = posValues[0] != 0.0f;
- missLast = posValues[count - 1] != 1.0f;
-
- stopCount += missFirst + missLast;
- storedPositions = new jfloat[stopCount];
-
- if (missFirst) {
- storedPositions[0] = 0.0f;
- }
-
- for (size_t i = missFirst; i < count + missFirst; i++) {
- storedPositions[i] = posValues[i - missFirst];
- }
-
- if (missLast) {
- storedPositions[stopCount - 1] = 1.0f;
- }
- } else {
- storedPositions = new jfloat[count];
- storedPositions[0] = 0.0f;
- const jfloat step = 1.0f / (count - 1);
- for (size_t i = 1; i < count - 1; i++) {
- storedPositions[i] = step * i;
- }
- storedPositions[count - 1] = 1.0f;
- }
-
- uint32_t* storedColors = new uint32_t[stopCount];
-
- if (missFirst) {
- storedColors[0] = static_cast<uint32_t>(colorValues[0]);
- }
-
- for (size_t i = missFirst; i < count + missFirst; i++) {
- storedColors[i] = static_cast<uint32_t>(colorValues[i - missFirst]);
- }
-
- if (missLast) {
- storedColors[stopCount - 1] = static_cast<uint32_t>(colorValues[count - 1]);
- }
-
- SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
- storedPositions, stopCount, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
- !shader->isOpaque());
-
- env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong LinearGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x0, jfloat y0, jfloat x1, jfloat y1, jint color0, jint color1, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- float* storedBounds = new float[4];
- storedBounds[0] = x0; storedBounds[1] = y0;
- storedBounds[2] = x1; storedBounds[3] = y1;
-
- 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 SkiaLinearGradientShader(storedBounds, storedColors,
- storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
- !shader->isOpaque());
-
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
static jlong LinearGradient_create2(JNIEnv* env, jobject o,
jfloat x0, jfloat y0, jfloat x1, jfloat y1,
jint color0, jint color1, jint tileMode)
@@ -300,67 +174,6 @@ static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jf
return reinterpret_cast<jlong>(s);
}
-static jlong RadialGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jfloat radius, jintArray colorArray, jfloatArray posArray, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- 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;
- const jfloat step = 1.0f / (count - 1);
- for (size_t i = 1; i < count - 1; i++) {
- storedPositions[i] = step * i;
- }
- storedPositions[count - 1] = 1.0f;
- }
-
- SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
- storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
- !shader->isOpaque());
-
- env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong RadialGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jfloat radius, jint color0, jint color1, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- 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->isOpaque());
-
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////
static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y,
@@ -393,65 +206,6 @@ static jlong SweepGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y,
return reinterpret_cast<jlong>(s);
}
-static jlong SweepGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jintArray colorArray, jfloatArray posArray) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- 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;
- const jfloat step = 1.0f / (count - 1);
- for (size_t i = 1; i < count - 1; i++) {
- storedPositions[i] = step * i;
- }
- storedPositions[count - 1] = 1.0f;
- }
-
- SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
- shader, NULL, !shader->isOpaque());
-
- env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong SweepGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jint color0, jint color1) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- 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 SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
- shader, NULL, !shader->isOpaque());
-
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong ComposeShader_create1(JNIEnv* env, jobject o,
@@ -476,40 +230,6 @@ static jlong ComposeShader_create2(JNIEnv* env, jobject o,
return reinterpret_cast<jlong>(shader);
}
-static jlong ComposeShader_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong shaderAHandle, jlong shaderBHandle, jint porterDuffModeHandle) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader *>(shaderHandle);
- SkiaShader* shaderA = reinterpret_cast<SkiaShader *>(shaderAHandle);
- SkiaShader* shaderB = reinterpret_cast<SkiaShader *>(shaderBHandle);
- SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(porterDuffModeHandle);
- SkXfermode::Mode mode = SkPorterDuff::ToXfermodeMode(porterDuffMode);
- SkiaShader* skiaShader = new SkiaComposeShader(shaderA, shaderB, mode, shader);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong ComposeShader_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader *>(shaderHandle);
- SkiaShader* shaderA = reinterpret_cast<SkiaShader *>(shaderAHandle);
- SkiaShader* shaderB = reinterpret_cast<SkiaShader *>(shaderBHandle);
- SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle);
- SkXfermode::Mode skiaMode;
- if (!SkXfermode::AsMode(mode, &skiaMode)) {
- // TODO: Support other modes
- skiaMode = SkXfermode::kSrcOver_Mode;
- }
- SkiaShader* skiaShader = new SkiaComposeShader(shaderA, shaderB, skiaMode, shader);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
static JNINativeMethod gColorMethods[] = {
@@ -518,41 +238,32 @@ static JNINativeMethod gColorMethods[] = {
};
static JNINativeMethod gShaderMethods[] = {
- { "nativeDestructor", "(JJ)V", (void*)Shader_destructor },
- { "nativeSetLocalMatrix", "(JJJ)V", (void*)Shader_setLocalMatrix }
+ { "nativeDestructor", "(J)V", (void*)Shader_destructor },
+ { "nativeSetLocalMatrix", "(JJ)V", (void*)Shader_setLocalMatrix }
};
static JNINativeMethod gBitmapShaderMethods[] = {
{ "nativeCreate", "(JII)J", (void*)BitmapShader_constructor },
- { "nativePostCreate", "(JJII)J", (void*)BitmapShader_postConstructor }
};
static JNINativeMethod gLinearGradientMethods[] = {
{ "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 },
{ "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 },
- { "nativePostCreate1", "(JFFFF[I[FI)J", (void*)LinearGradient_postCreate1 },
- { "nativePostCreate2", "(JFFFFIII)J", (void*)LinearGradient_postCreate2 }
};
static JNINativeMethod gRadialGradientMethods[] = {
{ "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 },
{ "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 },
- { "nativePostCreate1", "(JFFF[I[FI)J", (void*)RadialGradient_postCreate1 },
- { "nativePostCreate2", "(JFFFIII)J", (void*)RadialGradient_postCreate2 }
};
static JNINativeMethod gSweepGradientMethods[] = {
{ "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 },
{ "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 },
- { "nativePostCreate1", "(JFF[I[F)J", (void*)SweepGradient_postCreate1 },
- { "nativePostCreate2", "(JFFII)J", (void*)SweepGradient_postCreate2 }
};
static JNINativeMethod gComposeShaderMethods[] = {
{ "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 },
{ "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 },
- { "nativePostCreate1", "(JJJJ)J", (void*)ComposeShader_postCreate1 },
- { "nativePostCreate2", "(JJJI)J", (void*)ComposeShader_postCreate2 }
};
#include <android_runtime/AndroidRuntime.h>
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 50eb869..eda2400 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -45,7 +45,6 @@
#include <DisplayListRenderer.h>
#include <LayerRenderer.h>
#include <OpenGLRenderer.h>
-#include <SkiaShader.h>
#include <Stencil.h>
#include <Rect.h>
#include <RenderNode.h>
@@ -85,8 +84,6 @@ using namespace uirenderer;
#define RENDERER_LOGD(...)
#endif
-#define MODIFIER_SHADER 2
-
// ----------------------------------------------------------------------------
static struct {
@@ -616,24 +613,6 @@ static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
}
// ----------------------------------------------------------------------------
-// Shaders and color filters
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jint modifiers) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- if (modifiers & MODIFIER_SHADER) renderer->resetShader();
-}
-
-static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong shaderPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- SkiaShader* shader = reinterpret_cast<SkiaShader*>(shaderPtr);
- renderer->setupShader(shader);
-}
-
-
-// ----------------------------------------------------------------------------
// Draw filters
// ----------------------------------------------------------------------------
@@ -1091,9 +1070,6 @@ static JNINativeMethod gMethods[] = {
{ "nDrawPath", "(JJJ)V", (void*) android_view_GLES20Canvas_drawPath },
{ "nDrawLines", "(J[FIIJ)V", (void*) android_view_GLES20Canvas_drawLines },
- { "nResetModifiers", "(JI)V", (void*) android_view_GLES20Canvas_resetModifiers },
- { "nSetupShader", "(JJ)V", (void*) android_view_GLES20Canvas_setupShader },
-
{ "nSetupPaintFilter", "(JII)V", (void*) android_view_GLES20Canvas_setupPaintFilter },
{ "nResetPaintFilter", "(J)V", (void*) android_view_GLES20Canvas_resetPaintFilter },
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index b7673d8..3ab57c1 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -44,7 +44,6 @@ public class BitmapShader extends Shader {
mTileY = tileY;
final long b = bitmap.ni();
native_instance = nativeCreate(b, tileX.nativeInt, tileY.nativeInt);
- native_shader = nativePostCreate(native_instance, b, tileX.nativeInt, tileY.nativeInt);
}
/**
@@ -59,6 +58,4 @@ public class BitmapShader extends Shader {
private static native long nativeCreate(long native_bitmap, int shaderTileModeX,
int shaderTileModeY);
- private static native long nativePostCreate(long native_shader, long native_bitmap,
- int shaderTileModeX, int shaderTileModeY);
}
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 5109ffd..d7b2071 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -55,14 +55,6 @@ public class ComposeShader extends Shader {
mXferMode = mode;
native_instance = nativeCreate1(shaderA.native_instance, shaderB.native_instance,
(mode != null) ? mode.native_instance : 0);
- if (mode instanceof PorterDuffXfermode) {
- PorterDuff.Mode pdMode = ((PorterDuffXfermode) mode).mode;
- native_shader = nativePostCreate2(native_instance, shaderA.native_shader,
- shaderB.native_shader, pdMode != null ? pdMode.nativeInt : 0);
- } else {
- native_shader = nativePostCreate1(native_instance, shaderA.native_shader,
- shaderB.native_shader, mode != null ? mode.native_instance : 0);
- }
}
/** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
@@ -79,8 +71,6 @@ public class ComposeShader extends Shader {
mPorterDuffMode = mode;
native_instance = nativeCreate2(shaderA.native_instance, shaderB.native_instance,
mode.nativeInt);
- native_shader = nativePostCreate2(native_instance, shaderA.native_shader,
- shaderB.native_shader, mode.nativeInt);
}
/**
@@ -108,8 +98,4 @@ public class ComposeShader extends Shader {
long native_mode);
private static native long nativeCreate2(long native_shaderA, long native_shaderB,
int porterDuffMode);
- private static native long nativePostCreate1(long native_shader, long native_skiaShaderA,
- long native_skiaShaderB, long native_mode);
- private static native long nativePostCreate2(long native_shader, long native_skiaShaderA,
- long native_skiaShaderB, int porterDuffMode);
}
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 0eae67c..90cb217 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -66,8 +66,6 @@ public class LinearGradient extends Shader {
mPositions = positions;
mTileMode = tile;
native_instance = nativeCreate1(x0, y0, x1, y1, colors, positions, tile.nativeInt);
- native_shader = nativePostCreate1(native_instance, x0, y0, x1, y1, colors, positions,
- tile.nativeInt);
}
/** Create a shader that draws a linear gradient along a line.
@@ -90,8 +88,6 @@ public class LinearGradient extends Shader {
mColor1 = color1;
mTileMode = tile;
native_instance = nativeCreate2(x0, y0, x1, y1, color0, color1, tile.nativeInt);
- native_shader = nativePostCreate2(native_instance, x0, y0, x1, y1, color0, color1,
- tile.nativeInt);
}
/**
@@ -120,8 +116,4 @@ public class LinearGradient extends Shader {
int colors[], float positions[], int tileMode);
private native long nativeCreate2(float x0, float y0, float x1, float y1,
int color0, int color1, int tileMode);
- private native long nativePostCreate1(long native_shader, float x0, float y0, float x1, float y1,
- int colors[], float positions[], int tileMode);
- private native long nativePostCreate2(long native_shader, float x0, float y0, float x1, float y1,
- int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index c00c612..75c951a 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -66,8 +66,6 @@ public class RadialGradient extends Shader {
mPositions = positions;
mTileMode = tile;
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.
@@ -91,8 +89,6 @@ public class RadialGradient extends Shader {
mColor1 = color1;
mTileMode = tile;
native_instance = nativeCreate2(x, y, radius, color0, color1, tile.nativeInt);
- native_shader = nativePostCreate2(native_instance, x, y, radius, color0, color1,
- tile.nativeInt);
}
/**
@@ -121,10 +117,5 @@ public class RadialGradient extends Shader {
int colors[], float positions[], int tileMode);
private static native long nativeCreate2(float x, float y, float radius,
int color0, int color1, int tileMode);
-
- private static native long nativePostCreate1(long native_shader, float x, float y, float radius,
- int colors[], float positions[], int tileMode);
- private static native long nativePostCreate2(long native_shader, float x, float y, float radius,
- int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 94b4c4a..6870ab4 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -29,10 +29,6 @@ public class Shader {
* @hide
*/
public long native_instance;
- /**
- * @hide
- */
- public long native_shader;
private Matrix mLocalMatrix;
@@ -78,7 +74,7 @@ public class Shader {
*/
public void setLocalMatrix(Matrix localM) {
mLocalMatrix = localM;
- nativeSetLocalMatrix(native_instance, native_shader,
+ nativeSetLocalMatrix(native_instance,
localM == null ? 0 : localM.native_instance);
}
@@ -86,7 +82,7 @@ public class Shader {
try {
super.finalize();
} finally {
- nativeDestructor(native_instance, native_shader);
+ nativeDestructor(native_instance);
}
}
@@ -112,7 +108,7 @@ public class Shader {
}
}
- private static native void nativeDestructor(long native_shader, long native_skiaShader);
+ private static native void nativeDestructor(long native_shader);
private static native void nativeSetLocalMatrix(long native_shader,
- long native_skiaShader, long matrix_instance);
+ long matrix_instance);
}
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 21239f7..18a748f 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -63,7 +63,6 @@ public class SweepGradient extends Shader {
mColors = colors;
mPositions = positions;
native_instance = nativeCreate1(cx, cy, colors, positions);
- native_shader = nativePostCreate1(native_instance, cx, cy, colors, positions);
}
/**
@@ -81,7 +80,6 @@ public class SweepGradient extends Shader {
mColor0 = color0;
mColor1 = color1;
native_instance = nativeCreate2(cx, cy, color0, color1);
- native_shader = nativePostCreate2(native_instance, cx, cy, color0, color1);
}
/**
@@ -108,10 +106,5 @@ public class SweepGradient extends Shader {
private static native long nativeCreate1(float x, float y, int colors[], float positions[]);
private static native long nativeCreate2(float x, float y, int color0, int color1);
-
- private static native long nativePostCreate1(long native_shader, float cx, float cy,
- int[] colors, float[] positions);
- private static native long nativePostCreate2(long native_shader, float cx, float cy,
- int color0, int color1);
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 2e2ee15..5367663 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -33,6 +33,7 @@
#include "thread/TaskManager.h"
#include "AssetAtlas.h"
+#include "Extensions.h"
#include "FontRenderer.h"
#include "GammaFontRenderer.h"
#include "TextureCache.h"
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 45b6624..cbfab75 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -229,6 +229,11 @@ public:
return false;
}
+ if (op->mPaint && mOps[0].op->mPaint &&
+ op->mPaint->getShader() != mOps[0].op->mPaint->getShader()) {
+ return false;
+ }
+
/* Draw Modifiers compatibility check
*
* Shadows are ignored, as only text uses them, and in that case they are drawn
@@ -243,7 +248,6 @@ public:
*/
const DrawModifiers& lhsMod = lhs->mDrawModifiers;
const DrawModifiers& rhsMod = rhs->mDrawModifiers;
- if (lhsMod.mShader != rhsMod.mShader) return false;
// Draw filter testing expects bit fields to be clear if filter not set.
if (lhsMod.mHasDrawFilter != rhsMod.mHasDrawFilter) return false;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index dac86cb..96c6292 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -58,11 +58,6 @@ void DisplayListData::cleanupResources() {
caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
}
- for (size_t i = 0; i < shaders.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(shaders.itemAt(i));
- caches.resourceCache.destructorLocked(shaders.itemAt(i));
- }
-
for (size_t i = 0; i < sourcePaths.size(); i++) {
caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
}
@@ -92,7 +87,6 @@ void DisplayListData::cleanupResources() {
bitmapResources.clear();
ownedBitmapResources.clear();
patchResources.clear();
- shaders.clear();
sourcePaths.clear();
paints.clear();
regions.clear();
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index b2ead5b..11e78b0 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -56,7 +56,6 @@ class DisplayListRenderer;
class OpenGLRenderer;
class Rect;
class Layer;
-class SkiaShader;
class ClipRectOp;
class SaveLayerOp;
@@ -127,7 +126,6 @@ public:
SortedVector<const SkPath*> sourcePaths;
Vector<const SkRegion*> regions;
Vector<const SkMatrix*> matrices;
- Vector<SkiaShader*> shaders;
Vector<Layer*> layers;
uint32_t functorCount;
bool hasDrawOps;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index f1d70eb..0fd6ea4 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -208,9 +208,16 @@ protected:
if (!state.mMatrix.isSimple()) return false;
// check state/paint for transparency
- if (state.mDrawModifiers.mShader ||
- state.mAlpha != 1.0f ||
- (mPaint && mPaint->getAlpha() != 0xFF)) return false;
+ if (mPaint) {
+ if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
+ return false;
+ }
+ if (mPaint->getAlpha() != 0xFF) {
+ return false;
+ }
+ }
+
+ if (state.mAlpha != 1.0f) return false;
SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
return (mode == SkXfermode::kSrcOver_Mode ||
@@ -592,37 +599,6 @@ private:
const SkRegion* mRegion;
};
-class ResetShaderOp : public StateOp {
-public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.resetShader();
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOGS("ResetShader");
- }
-
- virtual const char* name() { return "ResetShader"; }
-};
-
-class SetupShaderOp : public StateOp {
-public:
- SetupShaderOp(SkiaShader* shader)
- : mShader(shader) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.setupShader(mShader);
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("SetupShader, shader %p", mShader);
- }
-
- virtual const char* name() { return "SetupShader"; }
-
-private:
- SkiaShader* mShader;
-};
-
class ResetPaintFilterOp : public StateOp {
public:
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index a4bce3a..26a81d3 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -47,7 +47,6 @@ DisplayListRenderer::~DisplayListRenderer() {
///////////////////////////////////////////////////////////////////////////////
DisplayListData* DisplayListRenderer::finishRecording() {
- mShaderMap.clear();
mPaintMap.clear();
mRegionMap.clear();
mPathMap.clear();
@@ -398,15 +397,6 @@ status_t DisplayListRenderer::drawRects(const float* rects, int count, const SkP
return DrawGlInfo::kStatusDone;
}
-void DisplayListRenderer::resetShader() {
- addStateOp(new (alloc()) ResetShaderOp());
-}
-
-void DisplayListRenderer::setupShader(SkiaShader* shader) {
- shader = refShader(shader);
- addStateOp(new (alloc()) SetupShaderOp(shader));
-}
-
void DisplayListRenderer::resetPaintFilter() {
addStateOp(new (alloc()) ResetPaintFilterOp());
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 185179a..79b59a0 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -99,9 +99,6 @@ public:
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
// Misc - should be implemented with SkPaint inspection
- virtual void resetShader();
- virtual void setupShader(SkiaShader* shader);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -273,21 +270,6 @@ private:
return bitmap;
}
- inline SkiaShader* refShader(SkiaShader* shader) {
- if (!shader) return NULL;
-
- SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
- // TODO: We also need to handle generation ID changes in compose shaders
- if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
- shaderCopy = shader->copy();
- // replaceValueFor() performs an add if the entry doesn't exist
- mShaderMap.replaceValueFor(shader, shaderCopy);
- mDisplayListData->shaders.add(shaderCopy);
- mCaches.resourceCache.incrementRefcount(shaderCopy);
- }
- return shaderCopy;
- }
-
inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
mDisplayListData->patchResources.add(patch);
mCaches.resourceCache.incrementRefcount(patch);
@@ -297,7 +279,6 @@ private:
DefaultKeyedVector<const SkPaint*, const SkPaint*> mPaintMap;
DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
- DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
Caches& mCaches;
DisplayListData* mDisplayListData;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 647c281..4407ab0 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -73,7 +73,7 @@ status_t TextSetupFunctor::operator ()(int what, void* data) {
}
}
renderer->setupDrawColorFilter(paint->getColorFilter());
- renderer->setupDrawShader();
+ renderer->setupDrawShader(paint->getShader());
renderer->setupDrawBlending(paint);
renderer->setupDrawProgram();
renderer->setupDrawModelView(kModelViewMode_Translate, false,
@@ -85,7 +85,7 @@ status_t TextSetupFunctor::operator ()(int what, void* data) {
renderer->setupDrawTexture(0);
renderer->setupDrawPureColorUniforms();
renderer->setupDrawColorFilterUniforms(paint->getColorFilter());
- renderer->setupDrawShaderUniforms(pureTranslate);
+ renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate);
renderer->setupDrawTextGammaUniforms();
return NO_ERROR;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4df97e6..727547f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <SkCanvas.h>
+#include <SkShader.h>
#include <SkTypeface.h>
#include <utils/Log.h>
@@ -37,6 +38,7 @@
#include "PathTessellator.h"
#include "Properties.h"
#include "ShadowTessellator.h"
+#include "SkiaShader.h"
#include "utils/GLUtils.h"
#include "Vector.h"
#include "VertexBuffer.h"
@@ -1053,6 +1055,45 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
#define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)
+// This class is purely for inspection. It inherits from SkShader, but Skia does not know how to
+// use it. The OpenGLRenderer will look at it to find its Layer and whether it is opaque.
+class LayerShader : public SkShader {
+public:
+ LayerShader(Layer* layer, const SkMatrix* localMatrix)
+ : INHERITED(localMatrix)
+ , mLayer(layer) {
+ }
+
+ virtual bool asACustomShader(void** data) const {
+ if (data) {
+ *data = static_cast<void*>(mLayer);
+ }
+ return true;
+ }
+
+ virtual bool isOpaque() const {
+ return !mLayer->isBlend();
+ }
+
+protected:
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) {
+ LOG_ALWAYS_FATAL("LayerShader should never be drawn with raster backend.");
+ }
+
+ virtual void flatten(SkWriteBuffer&) const {
+ LOG_ALWAYS_FATAL("LayerShader should never be flattened.");
+ }
+
+ virtual Factory getFactory() const {
+ LOG_ALWAYS_FATAL("LayerShader should never be created from a stream.");
+ return NULL;
+ }
+private:
+ // Unowned.
+ Layer* mLayer;
+ typedef SkShader INHERITED;
+};
+
void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
if (CC_UNLIKELY(layer->region.isEmpty())) return; // nothing to draw
@@ -1066,21 +1107,19 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
paint.setAntiAlias(true);
paint.setColor(SkColorSetARGB(int(getLayerAlpha(layer) * 255), 0, 0, 0));
- SkiaShader* oldShader = mDrawModifiers.mShader;
-
// create LayerShader to map SaveLayer content into subsequent draw
SkMatrix shaderMatrix;
shaderMatrix.setTranslate(rect.left, rect.bottom);
shaderMatrix.preScale(1, -1);
- SkiaLayerShader layerShader(layer, &shaderMatrix);
- mDrawModifiers.mShader = &layerShader;
+ LayerShader layerShader(layer, &shaderMatrix);
+ paint.setShader(&layerShader);
// Since the drawing primitive is defined in local drawing space,
// we don't need to modify the draw matrix
const SkPath* maskPath = layer->getConvexMask();
DRAW_DOUBLE_STENCIL(drawConvexPath(*maskPath, &paint));
- mDrawModifiers.mShader = oldShader;
+ paint.setShader(NULL);
restore();
return;
@@ -1615,9 +1654,9 @@ void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
mSetShaderColor = mDescription.setColorModulate(a);
}
-void OpenGLRenderer::setupDrawShader() {
- if (mDrawModifiers.mShader) {
- mDrawModifiers.mShader->describe(mDescription, mExtensions);
+void OpenGLRenderer::setupDrawShader(const SkShader* shader) {
+ if (shader != NULL) {
+ SkiaShader::describe(&mCaches, mDescription, mExtensions, *shader);
}
}
@@ -1643,15 +1682,21 @@ void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) {
}
}
+static bool isBlendedColorFilter(const SkColorFilter* filter) {
+ if (filter == NULL) {
+ return false;
+ }
+ return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
+}
+
void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) {
SkXfermode::Mode mode = layer->getMode();
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
+ // TODO: check shader blending, once we have shader drawing support for layers.
bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f ||
- (mColorSet && mColorA < 1.0f) ||
- (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
- layer->getColorFilter();
+ (mColorSet && mColorA < 1.0f) || isBlendedColorFilter(layer->getColorFilter());
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1661,8 +1706,8 @@ void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool sw
// argb=1,0,0,0
accountForClear(mode);
blend |= (mColorSet && mColorA < 1.0f) ||
- (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
- (paint && paint->getColorFilter());
+ (getShader(paint) && !getShader(paint)->isOpaque()) ||
+ isBlendedColorFilter(getColorFilter(paint));
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1693,8 +1738,8 @@ void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset,
}
}
-void OpenGLRenderer::setupDrawColorUniforms() {
- if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) {
+void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) {
+ if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) {
mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
}
}
@@ -1705,20 +1750,22 @@ void OpenGLRenderer::setupDrawPureColorUniforms() {
}
}
-void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
- if (mDrawModifiers.mShader) {
- if (ignoreTransform) {
- // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
- // because it was built into modelView / the geometry, and the SkiaShader needs to
- // compensate.
- mat4 modelViewWithoutTransform;
- modelViewWithoutTransform.loadInverse(*currentTransform());
- modelViewWithoutTransform.multiply(mModelViewMatrix);
- mModelViewMatrix.load(modelViewWithoutTransform);
- }
- mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
- mModelViewMatrix, *mSnapshot, &mTextureUnit);
+void OpenGLRenderer::setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform) {
+ if (shader == NULL) {
+ return;
+ }
+
+ if (ignoreTransform) {
+ // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
+ // because it was built into modelView / the geometry, and the description needs to
+ // compensate.
+ mat4 modelViewWithoutTransform;
+ modelViewWithoutTransform.loadInverse(*currentTransform());
+ modelViewWithoutTransform.multiply(mModelViewMatrix);
+ mModelViewMatrix.load(modelViewWithoutTransform);
}
+
+ SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit, mExtensions, *shader);
}
void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) {
@@ -2177,7 +2224,7 @@ status_t OpenGLRenderer::drawBitmap(const SkBitmap* bitmap,
// Apply a scale transform on the canvas only when a shader is in use
// Skia handles the ratio between the dst and src rects as a scale factor
// when a shader is set
- bool useScaleTransform = mDrawModifiers.mShader && scaled;
+ bool useScaleTransform = getShader(paint) && scaled;
bool ignoreTransform = false;
if (CC_LIKELY(currentTransform()->isPureTranslate() && !useScaleTransform)) {
@@ -2335,13 +2382,13 @@ status_t OpenGLRenderer::drawVertexBuffer(VertexBufferMode mode,
if (isAA) setupDrawAA();
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, isAA);
setupDrawProgram();
setupDrawModelView(kModelViewMode_Translate, useOffset, 0, 0, 0, 0);
- setupDrawColorUniforms();
+ setupDrawColorUniforms(getShader(paint));
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
const void* vertices = vertexBuffer.getBuffer();
bool force = mCaches.unbindMeshBuffer();
@@ -2646,7 +2693,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
const float sy = y - shadow->top + textShadow.dy;
const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * mSnapshot->alpha;
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
textShadow.color = SK_ColorWHITE;
}
@@ -2654,7 +2701,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
setupDrawWithTexture(true);
setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
@@ -2662,7 +2709,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
setupDrawTexture(shadow->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -2984,21 +3031,6 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
}
///////////////////////////////////////////////////////////////////////////////
-// Shaders
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::resetShader() {
- mDrawModifiers.mShader = NULL;
-}
-
-void OpenGLRenderer::setupShader(SkiaShader* shader) {
- mDrawModifiers.mShader = shader;
- if (mDrawModifiers.mShader) {
- mDrawModifiers.mShader->setCaches(mCaches);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Draw filters
///////////////////////////////////////////////////////////////////////////////
@@ -3056,7 +3088,7 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
setupDrawWithTexture(true);
setupDrawAlpha8Color(paint->getColor(), alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
@@ -3064,7 +3096,7 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -3230,7 +3262,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, const SkP
int color = paint->getColor();
// If a shader is set, preserve only the alpha
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
color |= 0x00ffffff;
}
@@ -3266,15 +3298,15 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, const SkP
setupDraw();
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawColorFilter(getColorFilter(paint));
setupDrawBlending(paint);
setupDrawProgram();
setupDrawDirtyRegionsDisabled();
setupDrawModelView(kModelViewMode_Translate, false,
0.0f, 0.0f, 0.0f, 0.0f, ignoreTransform);
- setupDrawColorUniforms();
- setupDrawShaderUniforms();
+ setupDrawColorUniforms(getShader(paint));
+ setupDrawShaderUniforms(getShader(paint));
setupDrawColorFilterUniforms(getColorFilter(paint));
if (dirty && hasLayer()) {
@@ -3290,21 +3322,21 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
const SkPaint* paint, bool ignoreTransform) {
int color = paint->getColor();
// If a shader is set, preserve only the alpha
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
color |= 0x00ffffff;
}
setupDraw();
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawColorFilter(getColorFilter(paint));
setupDrawBlending(paint);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
left, top, right, bottom, ignoreTransform);
- setupDrawColorUniforms();
- setupDrawShaderUniforms(ignoreTransform);
+ setupDrawColorUniforms(getShader(paint));
+ setupDrawShaderUniforms(getShader(paint), ignoreTransform);
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawSimpleMesh();
@@ -3417,7 +3449,7 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f
setupDrawAlpha8Color(color, alpha);
}
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
@@ -3425,7 +3457,7 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f
setupDrawTexture(texture);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms(ignoreTransform);
+ setupDrawShaderUniforms(getShader(paint), ignoreTransform);
setupDrawMesh(vertices, texCoords);
glDrawArrays(drawMode, 0, elementsCount);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b58b817..9a60036 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -26,7 +26,6 @@
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkRegion.h>
-#include <SkShader.h>
#include <SkXfermode.h>
#include <utils/Blur.h>
@@ -45,13 +44,15 @@
#include "Program.h"
#include "Rect.h"
#include "Renderer.h"
-#include "StatefulBaseRenderer.h"
#include "Snapshot.h"
+#include "StatefulBaseRenderer.h"
#include "UvMapper.h"
#include "Vertex.h"
#include "Caches.h"
#include "CanvasProperty.h"
+class SkShader;
+
namespace android {
namespace uirenderer {
@@ -59,7 +60,6 @@ class DeferredDisplayState;
class RenderNode;
class TextSetupFunctor;
class VertexBuffer;
-class SkiaShader;
struct DrawModifiers {
DrawModifiers() {
@@ -70,7 +70,6 @@ struct DrawModifiers {
memset(this, 0, sizeof(DrawModifiers));
}
- SkiaShader* mShader;
float mOverrideLayerAlpha;
// Draw filters
@@ -217,9 +216,6 @@ public:
status_t drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter);
- virtual void resetShader();
- virtual void setupShader(SkiaShader* shader);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -467,6 +463,14 @@ protected:
}
/**
+ * Safely retrieves the Shader from the given Paint. If the paint is
+ * null then null is returned.
+ */
+ static inline const SkShader* getShader(const SkPaint* paint) {
+ return paint ? paint->getShader() : NULL;
+ }
+
+ /**
* Set to true to suppress error checks at the end of a frame.
*/
virtual bool suppressErrorChecks() const {
@@ -838,7 +842,7 @@ private:
void setupDrawColor(float r, float g, float b, float a);
void setupDrawAlpha8Color(int color, int alpha);
void setupDrawTextGamma(const SkPaint* paint);
- void setupDrawShader();
+ void setupDrawShader(const SkShader* shader);
void setupDrawColorFilter(const SkColorFilter* filter);
void setupDrawBlending(const Layer* layer, bool swapSrcDst = false);
void setupDrawBlending(const SkPaint* paint, bool blend = true, bool swapSrcDst = false);
@@ -862,9 +866,17 @@ private:
*/
void setupDrawModelView(ModelViewMode mode, bool offset,
float left, float top, float right, float bottom, bool ignoreTransform = false);
- void setupDrawColorUniforms();
+ void setupDrawColorUniforms(bool hasShader);
void setupDrawPureColorUniforms();
- void setupDrawShaderUniforms(bool ignoreTransform = false);
+
+ /**
+ * Setup uniforms for the current shader.
+ *
+ * @param shader SkShader on the current paint.
+ *
+ * @param ignoreTransform Set to true to ignore the transform in shader.
+ */
+ void setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform = false);
void setupDrawColorFilterUniforms(const SkColorFilter* paint);
void setupDrawSimpleMesh();
void setupDrawTexture(GLuint texture);
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 57db816..4c2842c 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -35,7 +35,6 @@ class RenderNode;
class Layer;
class Matrix4;
class SkiaColorFilter;
-class SkiaShader;
class Patch;
enum DrawOpMode {
@@ -175,9 +174,6 @@ public:
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
// Misc - should be implemented with SkPaint inspection
- virtual void resetShader() = 0;
- virtual void setupShader(SkiaShader* shader) = 0;
-
virtual void resetPaintFilter() = 0;
virtual void setupPaintFilter(int clearBits, int setBits) = 0;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 13a3e8e..8b553d1 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -71,11 +71,6 @@ void ResourceCache::incrementRefcount(const SkPath* pathResource) {
incrementRefcount((void*) pathResource, kPath);
}
-void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
- SkSafeRef(shaderResource->getSkShader());
- incrementRefcount((void*) shaderResource, kShader);
-}
-
void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
incrementRefcount((void*) patchResource, kNinePatch);
}
@@ -104,11 +99,6 @@ void ResourceCache::incrementRefcountLocked(const SkPath* pathResource) {
incrementRefcountLocked((void*) pathResource, kPath);
}
-void ResourceCache::incrementRefcountLocked(SkiaShader* shaderResource) {
- SkSafeRef(shaderResource->getSkShader());
- incrementRefcountLocked((void*) shaderResource, kShader);
-}
-
void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) {
incrementRefcountLocked((void*) patchResource, kNinePatch);
}
@@ -132,11 +122,6 @@ void ResourceCache::decrementRefcount(const SkPath* pathResource) {
decrementRefcount((void*) pathResource);
}
-void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
- SkSafeUnref(shaderResource->getSkShader());
- decrementRefcount((void*) shaderResource);
-}
-
void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
@@ -168,11 +153,6 @@ void ResourceCache::decrementRefcountLocked(const SkPath* pathResource) {
decrementRefcountLocked((void*) pathResource);
}
-void ResourceCache::decrementRefcountLocked(SkiaShader* shaderResource) {
- SkSafeUnref(shaderResource->getSkShader());
- decrementRefcountLocked((void*) shaderResource);
-}
-
void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
decrementRefcountLocked((void*) patchResource);
}
@@ -227,25 +207,6 @@ void ResourceCache::destructorLocked(const SkBitmap* resource) {
}
}
-void ResourceCache::destructor(SkiaShader* resource) {
- Mutex::Autolock _l(mLock);
- destructorLocked(resource);
-}
-
-void ResourceCache::destructorLocked(SkiaShader* resource) {
- ssize_t index = mCache->indexOfKey(resource);
- ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
- if (ref == NULL) {
- // If we're not tracking this resource, just delete it
- delete resource;
- return;
- }
- ref->destroyed = true;
- if (ref->refCount == 0) {
- deleteResourceReferenceLocked(resource, ref);
- }
-}
-
void ResourceCache::destructor(Res_png_9patch* resource) {
Mutex::Autolock _l(mLock);
destructorLocked(resource);
@@ -333,11 +294,6 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource
}
}
break;
- case kShader: {
- SkiaShader* shader = (SkiaShader*) resource;
- delete shader;
- }
- break;
case kNinePatch: {
if (Caches::hasInstance()) {
Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 4097ba4..3864d4b 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -20,7 +20,6 @@
#include <cutils/compiler.h>
#include <SkBitmap.h>
-#include <SkiaShader.h>
#include <utils/KeyedVector.h>
@@ -36,7 +35,6 @@ namespace uirenderer {
*/
enum ResourceType {
kBitmap,
- kShader,
kNinePatch,
kPath,
kLayer
@@ -70,36 +68,30 @@ public:
void incrementRefcount(const SkPath* resource);
void incrementRefcount(const SkBitmap* resource);
- void incrementRefcount(SkiaShader* resource);
void incrementRefcount(const Res_png_9patch* resource);
void incrementRefcount(Layer* resource);
void incrementRefcountLocked(const SkPath* resource);
void incrementRefcountLocked(const SkBitmap* resource);
- void incrementRefcountLocked(SkiaShader* resource);
void incrementRefcountLocked(const Res_png_9patch* resource);
void incrementRefcountLocked(Layer* resource);
void decrementRefcount(const SkBitmap* resource);
void decrementRefcount(const SkPath* resource);
- void decrementRefcount(SkiaShader* resource);
void decrementRefcount(const Res_png_9patch* resource);
void decrementRefcount(Layer* resource);
void decrementRefcountLocked(const SkBitmap* resource);
void decrementRefcountLocked(const SkPath* resource);
- void decrementRefcountLocked(SkiaShader* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
void decrementRefcountLocked(Layer* resource);
void destructor(SkPath* resource);
void destructor(const SkBitmap* resource);
- void destructor(SkiaShader* resource);
void destructor(Res_png_9patch* resource);
void destructorLocked(SkPath* resource);
void destructorLocked(const SkBitmap* resource);
- void destructorLocked(SkiaShader* resource);
void destructorLocked(Res_png_9patch* resource);
bool recycle(SkBitmap* resource);
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 6a4a0c8..c672bc4 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -21,9 +21,10 @@
#include <SkMatrix.h>
#include "Caches.h"
+#include "Layer.h"
+#include "Matrix.h"
#include "SkiaShader.h"
#include "Texture.h"
-#include "Matrix.h"
namespace android {
namespace uirenderer {
@@ -54,89 +55,142 @@ static inline void bindUniformColor(int slot, uint32_t color) {
a);
}
-///////////////////////////////////////////////////////////////////////////////
-// Base shader
-///////////////////////////////////////////////////////////////////////////////
-
-void SkiaShader::copyFrom(const SkiaShader& shader) {
- mType = shader.mType;
- mKey = shader.mKey;
- mTileX = shader.mTileX;
- mTileY = shader.mTileY;
- mBlend = shader.mBlend;
- mUnitMatrix = shader.mUnitMatrix;
- mShaderMatrix = shader.mShaderMatrix;
- mGenerationId = shader.mGenerationId;
+static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
+ caches->bindTexture(texture->id);
+ texture->setWrapST(wrapS, wrapT);
}
-SkiaShader::SkiaShader(): mCaches(NULL) {
-}
+/**
+ * Compute the matrix to transform to screen space.
+ * @param screenSpace Output param for the computed matrix.
+ * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
+ * or identity.
+ * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
+ * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
+ */
+static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
+ const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
+ mat4 shaderMatrix;
+ // uses implicit construction
+ shaderMatrix.loadInverse(localMatrix);
+ // again, uses implicit construction
+ screenSpace.loadMultiply(unitMatrix, shaderMatrix);
+ screenSpace.multiply(modelViewMatrix);
+}
+
+// Returns true if one is a bitmap and the other is a gradient
+static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
+ return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
+ || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
+}
+
+SkiaShaderType SkiaShader::getType(const SkShader& shader) {
+ // First check for a gradient shader.
+ switch (shader.asAGradient(NULL)) {
+ case SkShader::kNone_GradientType:
+ // Not a gradient shader. Fall through to check for other types.
+ break;
+ case SkShader::kLinear_GradientType:
+ case SkShader::kRadial_GradientType:
+ case SkShader::kSweep_GradientType:
+ return kGradient_SkiaShaderType;
+ default:
+ // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
+ return kNone_SkiaShaderType;
+ }
-SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, const SkMatrix* matrix, bool blend):
- mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend),
- mCaches(NULL) {
- setMatrix(matrix);
- mGenerationId = 0;
-}
+ // The shader is not a gradient. Check for a bitmap shader.
+ if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
+ return kBitmap_SkiaShaderType;
+ }
-SkiaShader::~SkiaShader() {
-}
+ // Check for a ComposeShader.
+ SkShader::ComposeRec rec;
+ if (shader.asACompose(&rec)) {
+ const SkiaShaderType shaderAType = getType(*rec.fShaderA);
+ const SkiaShaderType shaderBType = getType(*rec.fShaderB);
+
+ // Compose is only supported if one is a bitmap and the other is a
+ // gradient. Otherwise, return None to skip.
+ if (!bitmapAndGradient(shaderAType, shaderBType)) {
+ return kNone_SkiaShaderType;
+ }
+ return kCompose_SkiaShaderType;
+ }
-void SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
-}
+ if (shader.asACustomShader(NULL)) {
+ return kLayer_SkiaShaderType;
+ }
-void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit) {
+ return kNone_SkiaShaderType;
}
-void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
- mCaches->bindTexture(texture->id);
- texture->setWrapST(wrapS, wrapT);
+typedef void (*describeProc)(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+
+describeProc gDescribeProc[] = {
+ InvalidSkiaShader::describe,
+ SkiaBitmapShader::describe,
+ SkiaGradientShader::describe,
+ SkiaComposeShader::describe,
+ SkiaLayerShader::describe,
+};
+
+typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+
+setupProgramProc gSetupProgramProc[] = {
+ InvalidSkiaShader::setupProgram,
+ SkiaBitmapShader::setupProgram,
+ SkiaGradientShader::setupProgram,
+ SkiaComposeShader::setupProgram,
+ SkiaLayerShader::setupProgram,
+};
+
+void SkiaShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ gDescribeProc[getType(shader)](caches, description, extensions, shader);
}
-void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
- screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
- screenSpace.multiply(modelView);
+void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+
+ gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
}
///////////////////////////////////////////////////////////////////////////////
// Layer shader
///////////////////////////////////////////////////////////////////////////////
-SkiaLayerShader::SkiaLayerShader(Layer* layer, const SkMatrix* matrix):
- SkiaShader(kBitmap, NULL, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- matrix, layer->isBlend()), mLayer(layer) {
- updateLocalMatrix(matrix);
-}
-
-SkiaShader* SkiaLayerShader::copy() {
- SkiaLayerShader* copy = new SkiaLayerShader();
- copy->copyFrom(*this);
- copy->mLayer = mLayer;
- return copy;
-}
-
-void SkiaLayerShader::describe(ProgramDescription& description, const Extensions& extensions) {
+void SkiaLayerShader::describe(Caches*, ProgramDescription& description,
+ const Extensions&, const SkShader& shader) {
description.hasBitmap = true;
}
-void SkiaLayerShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
+void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions&, const SkShader& shader) {
+ Layer* layer;
+ if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
+ LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
+ }
+
GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
+ caches->activeTexture(textureSlot);
- const float width = mLayer->getWidth();
- const float height = mLayer->getHeight();
+ const float width = layer->getWidth();
+ const float height = layer->getHeight();
mat4 textureTransform;
- computeScreenSpaceMatrix(textureTransform, modelView);
+ computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
+
// Uniforms
- mLayer->bindTexture();
- mLayer->setWrap(GL_CLAMP_TO_EDGE);
- mLayer->setFilter(GL_LINEAR);
+ layer->bindTexture();
+ layer->setWrap(GL_CLAMP_TO_EDGE);
+ layer->setFilter(GL_LINEAR);
+ Program* program = caches->currentProgram;
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
@@ -147,67 +201,99 @@ void SkiaLayerShader::setupProgram(Program* program, const mat4& modelView,
// Bitmap shader
///////////////////////////////////////////////////////////////////////////////
-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);
-}
-
-SkiaShader* SkiaBitmapShader::copy() {
- SkiaBitmapShader* copy = new SkiaBitmapShader();
- copy->copyFrom(*this);
- copy->mBitmap = mBitmap;
- return copy;
-}
+struct BitmapShaderInfo {
+ float width;
+ float height;
+ GLenum wrapS;
+ GLenum wrapT;
+ Texture* texture;
+};
-void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
- Texture* texture = mCaches->textureCache.get(mBitmap);
- if (!texture) return;
- mTexture = texture;
+static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
+ BitmapShaderInfo* shaderInfo,
+ const Extensions& extensions,
+ const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
+ Texture* texture = caches->textureCache.get(&bitmap);
+ if (!texture) return false;
const float width = texture->width;
const float height = texture->height;
+ GLenum wrapS, wrapT;
- description.hasBitmap = true;
+ if (description) {
+ description->hasBitmap = true;
+ }
// The driver does not support non-power of two mirrored/repeated
// textures, so do it ourselves
if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
- (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
- description.isBitmapNpot = true;
- description.bitmapWrapS = gTileModes[mTileX];
- description.bitmapWrapT = gTileModes[mTileY];
- mWrapS = GL_CLAMP_TO_EDGE;
- mWrapT = GL_CLAMP_TO_EDGE;
+ (tileModes[0] != SkShader::kClamp_TileMode ||
+ tileModes[1] != SkShader::kClamp_TileMode)) {
+ if (description) {
+ description->isBitmapNpot = true;
+ description->bitmapWrapS = gTileModes[tileModes[0]];
+ description->bitmapWrapT = gTileModes[tileModes[1]];
+ }
+ wrapS = GL_CLAMP_TO_EDGE;
+ wrapT = GL_CLAMP_TO_EDGE;
} else {
- mWrapS = gTileModes[mTileX];
- mWrapT = gTileModes[mTileY];
+ wrapS = gTileModes[tileModes[0]];
+ wrapT = gTileModes[tileModes[1]];
+ }
+
+ if (shaderInfo) {
+ shaderInfo->width = width;
+ shaderInfo->height = height;
+ shaderInfo->wrapS = wrapS;
+ shaderInfo->wrapT = wrapT;
+ shaderInfo->texture = texture;
}
+ return true;
}
-void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot&, GLuint* textureUnit) {
+void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
+ LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
+ }
+ bitmapShaderHelper(caches, &description, NULL, extensions, bitmap, xy);
+}
+
+void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
+ LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
+ }
+
GLuint textureSlot = (*textureUnit)++;
Caches::getInstance().activeTexture(textureSlot);
- Texture* texture = mTexture;
- mTexture = NULL;
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
+ BitmapShaderInfo shaderInfo;
+ if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) {
+ return;
+ }
- const float width = texture->width;
- const float height = texture->height;
+ Program* program = caches->currentProgram;
+ Texture* texture = shaderInfo.texture;
+
+ const AutoTexture autoCleanup(texture);
mat4 textureTransform;
- computeScreenSpaceMatrix(textureTransform, modelView);
+ computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
// Uniforms
- bindTexture(texture, mWrapS, mWrapT);
+ bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
texture->setFilter(GL_LINEAR);
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
- glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
+ glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width,
+ 1.0f / shaderInfo.height);
}
///////////////////////////////////////////////////////////////////////////////
@@ -225,74 +311,6 @@ static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
matrix->postScale(inv, inv);
}
-SkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors,
- float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
- mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
- SkPoint points[2];
- points[0].set(bounds[0], bounds[1]);
- points[1].set(bounds[2], bounds[3]);
-
- SkMatrix unitMatrix;
- toUnitMatrix(points, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
-
- updateLocalMatrix(matrix);
-
- mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
-}
-
-SkiaLinearGradientShader::~SkiaLinearGradientShader() {
- delete[] mBounds;
- delete[] mColors;
- delete[] mPositions;
-}
-
-SkiaShader* SkiaLinearGradientShader::copy() {
- SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
- copy->copyFrom(*this);
- copy->mBounds = new float[4];
- memcpy(copy->mBounds, mBounds, sizeof(float) * 4);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaLinearGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
- description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientLinear;
- description.isSimpleGradient = mIsSimple;
-}
-
-void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot&, GLuint* textureUnit) {
- if (CC_UNLIKELY(!mIsSimple)) {
- GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
-
- Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
-
- // Uniforms
- bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
- glUniform1i(program->getUniform("gradientSampler"), textureSlot);
- } else {
- bindUniformColor(program->getUniform("startColor"), mColors[0]);
- bindUniformColor(program->getUniform("endColor"), mColors[1]);
- }
-
- Caches::getInstance().dither.setupProgram(program, textureUnit);
-
- mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
- glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
-
///////////////////////////////////////////////////////////////////////////////
// Circular gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -304,37 +322,6 @@ static void toCircularUnitMatrix(const float x, const float y, const float radiu
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, colors, positions, count, key,
- tileMode, matrix, blend) {
- SkMatrix unitMatrix;
- toCircularUnitMatrix(x, y, radius, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
-
- updateLocalMatrix(matrix);
-}
-
-SkiaShader* SkiaCircularGradientShader::copy() {
- SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
- copy->copyFrom(*this);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaCircularGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
- description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientCircular;
- description.isSimpleGradient = mIsSimple;
-}
-
///////////////////////////////////////////////////////////////////////////////
// Sweep gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -343,74 +330,103 @@ 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),
- mColors(colors), mPositions(positions), mCount(count) {
- SkMatrix unitMatrix;
- toSweepUnitMatrix(x, y, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
-
- updateLocalMatrix(matrix);
-
- mIsSimple = count == 2;
-}
-
-SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, uint32_t* colors,
- float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaShader(type, key, tileMode, tileMode, matrix, blend),
- mColors(colors), mPositions(positions), mCount(count) {
- // protected method, that doesn't setup mUnitMatrix - should be handled by subclass
-
- mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
-}
-
-SkiaSweepGradientShader::~SkiaSweepGradientShader() {
- delete[] mColors;
- delete[] mPositions;
-}
-
-SkiaShader* SkiaSweepGradientShader::copy() {
- SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
- copy->copyFrom(*this);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
+///////////////////////////////////////////////////////////////////////////////
+// Common gradient code
+///////////////////////////////////////////////////////////////////////////////
-void SkiaSweepGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
+static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
+ return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
+}
+
+void SkiaGradientShader::describe(Caches*, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkShader::GradientInfo gradInfo;
+ gradInfo.fColorCount = 0;
+ gradInfo.fColors = NULL;
+ gradInfo.fColorOffsets = NULL;
+
+ switch (shader.asAGradient(&gradInfo)) {
+ case SkShader::kLinear_GradientType:
+ description.gradientType = ProgramDescription::kGradientLinear;
+ break;
+ case SkShader::kRadial_GradientType:
+ description.gradientType = ProgramDescription::kGradientCircular;
+ break;
+ case SkShader::kSweep_GradientType:
+ description.gradientType = ProgramDescription::kGradientSweep;
+ break;
+ default:
+ // Do nothing. This shader is unsupported.
+ return;
+ }
description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientSweep;
- description.isSimpleGradient = mIsSimple;
-}
-
-void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
- if (CC_UNLIKELY(!mIsSimple)) {
+ description.isSimpleGradient = isSimpleGradient(gradInfo);
+}
+
+void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions&, const SkShader& shader) {
+ // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
+ // how much space has been allocated for fColors and fColorOffsets. 10 was chosen
+ // arbitrarily, but should be >= 2.
+ // As output, it tells the number of actual colors/offsets in the gradient.
+ const int COLOR_COUNT = 10;
+ SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
+ SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
+
+ SkShader::GradientInfo gradInfo;
+ gradInfo.fColorCount = COLOR_COUNT;
+ gradInfo.fColors = colorStorage.get();
+ gradInfo.fColorOffsets = positionStorage.get();
+
+ SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
+
+ Program* program = caches->currentProgram;
+ if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
+ if (gradInfo.fColorCount > COLOR_COUNT) {
+ // There was not enough room in our arrays for all the colors and offsets. Try again,
+ // now that we know the true number of colors.
+ gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
+ gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
+
+ shader.asAGradient(&gradInfo);
+ }
GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
+ caches->activeTexture(textureSlot);
- Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
+#ifndef SK_SCALAR_IS_FLOAT
+ #error Need to convert gradInfo.fColorOffsets to float!
+#endif
+ Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
+ gradInfo.fColorCount);
// Uniforms
- bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
+ bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
glUniform1i(program->getUniform("gradientSampler"), textureSlot);
} else {
- bindUniformColor(program->getUniform("startColor"), mColors[0]);
- bindUniformColor(program->getUniform("endColor"), mColors[1]);
+ bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]);
+ bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]);
}
- mCaches->dither.setupProgram(program, textureUnit);
+ caches->dither.setupProgram(program, textureUnit);
+
+ SkMatrix unitMatrix;
+ switch (gradType) {
+ case SkShader::kLinear_GradientType:
+ toUnitMatrix(gradInfo.fPoint, &unitMatrix);
+ break;
+ case SkShader::kRadial_GradientType:
+ toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
+ gradInfo.fRadius[0], &unitMatrix);
+ break;
+ case SkShader::kSweep_GradientType:
+ toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
+ }
mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
+ computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}
@@ -418,49 +434,39 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi
// Compose shader
///////////////////////////////////////////////////////////////////////////////
-SkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
- SkXfermode::Mode mode, SkShader* key):
- SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- NULL, first->blend() || second->blend()),
- mFirst(first), mSecond(second), mMode(mode), mCleanup(false) {
-}
-
-SkiaComposeShader::~SkiaComposeShader() {
- if (mCleanup) {
- delete mFirst;
- delete mSecond;
+void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkShader::ComposeRec rec;
+ if (!shader.asACompose(&rec)) {
+ LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
}
-}
-
-SkiaShader* SkiaComposeShader::copy() {
- SkiaComposeShader* copy = new SkiaComposeShader();
- copy->copyFrom(*this);
- copy->mFirst = mFirst->copy();
- copy->mSecond = mSecond->copy();
- copy->mMode = mMode;
- copy->cleanup();
- return copy;
-}
-
-void SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
- mFirst->describe(description, extensions);
- mSecond->describe(description, extensions);
- if (mFirst->type() == kBitmap) {
+ SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
+ SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
+ if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
description.isBitmapFirst = true;
}
- description.shadersMode = mMode;
+ if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
+ // TODO: Support other modes.
+ description.shadersMode = SkXfermode::kSrcOver_Mode;
+ }
}
-void SkiaComposeShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
+void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ SkShader::ComposeRec rec;
+ if (!shader.asACompose(&rec)) {
+ LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
+ }
+
// Apply this compose shader's local transform and pass it down to
// the child shaders. They will in turn apply their local transform
// to this matrix.
mat4 transform;
- computeScreenSpaceMatrix(transform, modelView);
+ computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
- mFirst->setupProgram(program, transform, snapshot, textureUnit);
- mSecond->setupProgram(program, transform, snapshot, textureUnit);
+ SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
+ SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
}
}; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 9f30257..034c3f6 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -28,249 +28,90 @@
#include "ProgramCache.h"
#include "TextureCache.h"
#include "GradientCache.h"
-#include "Snapshot.h"
namespace android {
namespace uirenderer {
class Caches;
-
-///////////////////////////////////////////////////////////////////////////////
-// Base shader
-///////////////////////////////////////////////////////////////////////////////
+class Layer;
/**
- * Represents a Skia shader. A shader will modify the GL context and active
- * program to recreate the original effect.
+ * Type of Skia shader in use.
*/
+enum SkiaShaderType {
+ kNone_SkiaShaderType,
+ kBitmap_SkiaShaderType,
+ kGradient_SkiaShaderType,
+ kCompose_SkiaShaderType,
+ kLayer_SkiaShaderType
+};
+
class SkiaShader {
public:
- /**
- * Type of Skia shader in use.
- */
- enum Type {
- kNone,
- kBitmap,
- kLinearGradient,
- kCircularGradient,
- kSweepGradient,
- kCompose
- };
-
- ANDROID_API SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, const 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 setCaches(Caches& caches) {
- mCaches = &caches;
- }
-
- uint32_t getGenerationId() {
- return mGenerationId;
- }
-
- void setMatrix(const SkMatrix* matrix) {
- updateLocalMatrix(matrix);
- mGenerationId++;
+ static SkiaShaderType getType(const SkShader& shader);
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+};
+
+class InvalidSkiaShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ // This shader is unsupported. Skip it.
}
-
- void updateLocalMatrix(const SkMatrix* matrix) {
- if (matrix) {
- mat4 localMatrix(*matrix);
- mShaderMatrix.loadInverse(localMatrix);
- } else {
- mShaderMatrix.loadIdentity();
- }
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ // This shader is unsupported. Skip it.
}
- 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;
-
- Caches* mCaches;
-
- mat4 mUnitMatrix;
- mat4 mShaderMatrix;
-
-private:
- uint32_t mGenerationId;
-}; // struct SkiaShader
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Implementations
-///////////////////////////////////////////////////////////////////////////////
-
+};
/**
* A shader that draws a layer.
*/
-struct SkiaLayerShader: public SkiaShader {
- SkiaLayerShader(Layer* layer, const SkMatrix* matrix);
- SkiaShader* copy();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-private:
- SkiaLayerShader() {
- }
-
- Layer* mLayer;
-}; // struct SkiaLayerShader
+class SkiaLayerShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+}; // class SkiaLayerShader
/**
* A shader that draws a bitmap.
*/
-struct SkiaBitmapShader: public SkiaShader {
- ANDROID_API 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);
-
-private:
- SkiaBitmapShader() : mBitmap(NULL), mTexture(NULL) {
- }
-
- SkBitmap* mBitmap;
- Texture* mTexture;
- GLenum mWrapS;
- GLenum mWrapT;
-}; // struct SkiaBitmapShader
-
-/**
- * A shader that draws a linear gradient.
- */
-struct SkiaLinearGradientShader: public SkiaShader {
- ANDROID_API 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);
+class SkiaBitmapShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-private:
- SkiaLinearGradientShader() {
- }
- bool mIsSimple;
- float* mBounds;
- uint32_t* mColors;
- float* mPositions;
- int mCount;
-}; // struct SkiaLinearGradientShader
+}; // class SkiaBitmapShader
/**
- * A shader that draws a sweep gradient.
+ * A shader that draws one of three types of gradient, depending on shader param.
*/
-struct SkiaSweepGradientShader: public SkiaShader {
- ANDROID_API 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);
-
-protected:
- SkiaSweepGradientShader(Type type, uint32_t* colors, float* positions,
- int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
- SkiaSweepGradientShader() {
- }
-
- bool mIsSimple;
- uint32_t* mColors;
- float* mPositions;
- int mCount;
-}; // struct SkiaSweepGradientShader
-
-/**
- * A shader that draws a circular gradient.
- */
-struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
- ANDROID_API 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
+class SkiaGradientShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+};
/**
* A shader that draws two shaders, composited with an xfermode.
*/
-struct SkiaComposeShader: public SkiaShader {
- ANDROID_API SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode,
- SkShader* key);
- ~SkiaComposeShader();
- SkiaShader* copy();
-
- void setCaches(Caches& caches) {
- SkiaShader::setCaches(caches);
- mFirst->setCaches(caches);
- mSecond->setCaches(caches);
- }
-
- 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
+class SkiaComposeShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+}; // class SkiaComposeShader
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 34e2265..60b4b96 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -34,7 +34,7 @@ namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
TextureCache::TextureCache():
- mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
+ mCache(LruCache<const SkPixelRef*, Texture*>::kUnlimitedCapacity),
mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) {
char property[PROPERTY_VALUE_MAX];
@@ -58,7 +58,7 @@ TextureCache::TextureCache():
}
TextureCache::TextureCache(uint32_t maxByteSize):
- mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
+ mCache(LruCache<const SkPixelRef*, Texture*>::kUnlimitedCapacity),
mSize(0), mMaxSize(maxByteSize) {
init();
}
@@ -103,7 +103,7 @@ void TextureCache::setFlushRate(float flushRate) {
// Callbacks
///////////////////////////////////////////////////////////////////////////////
-void TextureCache::operator()(const SkBitmap*&, Texture*& texture) {
+void TextureCache::operator()(const SkPixelRef*&, Texture*& texture) {
// This will be called already locked
if (texture) {
mSize -= texture->bitmapSize;
@@ -122,7 +122,7 @@ void TextureCache::operator()(const SkBitmap*&, Texture*& texture) {
///////////////////////////////////////////////////////////////////////////////
void TextureCache::resetMarkInUse() {
- LruCache<const SkBitmap*, Texture*>::Iterator iter(mCache);
+ LruCache<const SkPixelRef*, Texture*>::Iterator iter(mCache);
while (iter.next()) {
iter.value()->isInUse = false;
}
@@ -140,7 +140,7 @@ bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) {
// Returns a prepared Texture* that either is already in the cache or can fit
// in the cache (and is thus added to the cache)
Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
- Texture* texture = mCache.get(bitmap);
+ Texture* texture = mCache.get(bitmap->pixelRef());
if (!texture) {
if (!canMakeTextureFromBitmap(bitmap)) {
@@ -170,7 +170,7 @@ Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
if (mDebugEnabled) {
ALOGD("Texture created, size = %d", size);
}
- mCache.put(bitmap, texture);
+ mCache.put(bitmap->pixelRef(), texture);
}
} else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
// Texture was in the cache but is dirty, re-upload
@@ -218,7 +218,7 @@ Texture* TextureCache::getTransient(const SkBitmap* bitmap) {
}
void TextureCache::remove(const SkBitmap* bitmap) {
- mCache.remove(bitmap);
+ mCache.remove(bitmap->pixelRef());
}
void TextureCache::removeDeferred(const SkBitmap* bitmap) {
@@ -231,7 +231,7 @@ void TextureCache::clearGarbage() {
size_t count = mGarbage.size();
for (size_t i = 0; i < count; i++) {
const SkBitmap* bitmap = mGarbage.itemAt(i);
- mCache.remove(bitmap);
+ mCache.remove(bitmap->pixelRef());
delete bitmap;
}
mGarbage.clear();
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 48a10c2..e5b5c1a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -49,7 +49,7 @@ namespace uirenderer {
* Any texture added to the cache causing the cache to grow beyond the maximum
* allowed size will also cause the oldest texture to be kicked out.
*/
-class TextureCache: public OnEntryRemoved<const SkBitmap*, Texture*> {
+class TextureCache: public OnEntryRemoved<const SkPixelRef*, Texture*> {
public:
TextureCache();
TextureCache(uint32_t maxByteSize);
@@ -59,7 +59,7 @@ public:
* Used as a callback when an entry is removed from the cache.
* Do not invoke directly.
*/
- void operator()(const SkBitmap*& bitmap, Texture*& texture);
+ void operator()(const SkPixelRef*& pixelRef, Texture*& texture);
/**
* Resets all Textures to not be marked as in use
@@ -147,7 +147,7 @@ private:
void init();
- LruCache<const SkBitmap*, Texture*> mCache;
+ LruCache<const SkPixelRef*, Texture*> mCache;
uint32_t mSize;
uint32_t mMaxSize;
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
index 6ad01a0..0f4e122 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
@@ -302,6 +302,36 @@ public abstract class DisplayModifier {
paint.setShader(ResourceModifiers.instance().mVertGradient);
}
});
+ put("radGradient", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mRadGradient);
+ }
+ });
+ put("sweepGradient", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mSweepGradient);
+ }
+ });
+ put("composeShader", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mComposeShader);
+ }
+ });
+ put("bad composeShader", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mBadComposeShader);
+ }
+ });
+ put("bad composeShader 2", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mAnotherBadComposeShader);
+ }
+ });
}
});
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
index c705443..d522481 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
@@ -23,7 +23,11 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Color;
+import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
+import android.graphics.PorterDuff;
+import android.graphics.RadialGradient;
+import android.graphics.SweepGradient;
import android.graphics.Matrix;
import android.graphics.Shader;
@@ -38,6 +42,11 @@ public class ResourceModifiers {
public final LinearGradient mHorGradient;
public final LinearGradient mDiagGradient;
public final LinearGradient mVertGradient;
+ public final RadialGradient mRadGradient;
+ public final SweepGradient mSweepGradient;
+ public final ComposeShader mComposeShader;
+ public final ComposeShader mBadComposeShader;
+ public final ComposeShader mAnotherBadComposeShader;
public final Bitmap mBitmap;
private final Matrix mMtx1;
private final Matrix mMtx2;
@@ -90,6 +99,12 @@ public class ResourceModifiers {
mVertGradient = new LinearGradient(0.0f, 0.0f, 0.0f, mDrawHeight / 2.0f,
Color.YELLOW, Color.MAGENTA, Shader.TileMode.MIRROR);
+ mSweepGradient = new SweepGradient(mDrawWidth / 2.0f, mDrawHeight / 2.0f,
+ Color.YELLOW, Color.MAGENTA);
+
+ mComposeShader = new ComposeShader(mRepeatShader, mHorGradient,
+ PorterDuff.Mode.MULTIPLY);
+
final float width = mBitmap.getWidth() / 8.0f;
final float height = mBitmap.getHeight() / 8.0f;
@@ -106,6 +121,16 @@ public class ResourceModifiers {
0xff00ff00, 0xff0000ff, 0xffff0000, 0xff00ff00,
0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ff0000,
};
+
+ // Use a repeating gradient with many colors to test the non simple case.
+ mRadGradient = new RadialGradient(mDrawWidth / 4.0f, mDrawHeight / 4.0f, 4.0f,
+ mBitmapColors, null, Shader.TileMode.REPEAT);
+
+ mBadComposeShader = new ComposeShader(mRadGradient, mComposeShader,
+ PorterDuff.Mode.MULTIPLY);
+
+ mAnotherBadComposeShader = new ComposeShader(mRadGradient, mVertGradient,
+ PorterDuff.Mode.MULTIPLY);
}
}