Merge "DO NOT MERGE Inspect SkShader to determine hw shader." into lmp-preview-dev
This commit is contained in:
@ -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;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
@ -615,24 +612,6 @@ static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
|
||||
env->ReleaseFloatArrayElements(points, storage, 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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 },
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "thread/TaskManager.h"
|
||||
|
||||
#include "AssetAtlas.h"
|
||||
#include "Extensions.h"
|
||||
#include "FontRenderer.h"
|
||||
#include "GammaFontRenderer.h"
|
||||
#include "TextureCache.h"
|
||||
|
@ -230,6 +230,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
|
||||
@ -244,7 +249,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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -47,7 +47,6 @@ DisplayListRenderer::~DisplayListRenderer() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DisplayListData* DisplayListRenderer::finishRecording() {
|
||||
mShaderMap.clear();
|
||||
mPaintMap.clear();
|
||||
mRegionMap.clear();
|
||||
mPathMap.clear();
|
||||
@ -394,15 +393,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());
|
||||
}
|
||||
|
@ -95,9 +95,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);
|
||||
|
||||
@ -269,21 +266,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);
|
||||
@ -293,7 +275,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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
@ -1627,9 +1666,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1655,15 +1694,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);
|
||||
}
|
||||
|
||||
@ -1673,8 +1718,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);
|
||||
}
|
||||
|
||||
@ -1717,8 +1762,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);
|
||||
}
|
||||
}
|
||||
@ -1729,20 +1774,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) {
|
||||
@ -2201,7 +2248,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)) {
|
||||
@ -2359,13 +2406,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();
|
||||
@ -2670,7 +2717,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;
|
||||
}
|
||||
|
||||
@ -2678,7 +2725,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,
|
||||
@ -2686,7 +2733,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);
|
||||
@ -3007,21 +3054,6 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
|
||||
return DrawGlInfo::kStatusDrew;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Shaders
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::resetShader() {
|
||||
mDrawModifiers.mShader = NULL;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupShader(SkiaShader* shader) {
|
||||
mDrawModifiers.mShader = shader;
|
||||
if (mDrawModifiers.mShader) {
|
||||
mDrawModifiers.mShader->setCaches(mCaches);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Draw filters
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -3080,7 +3112,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,
|
||||
@ -3088,7 +3120,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);
|
||||
@ -3254,7 +3286,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;
|
||||
}
|
||||
|
||||
@ -3290,15 +3322,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()) {
|
||||
@ -3314,21 +3346,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();
|
||||
|
||||
@ -3441,7 +3473,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();
|
||||
@ -3449,7 +3481,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);
|
||||
|
@ -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);
|
||||
|
||||
@ -466,6 +462,14 @@ protected:
|
||||
return paint ? paint->getColorFilter() : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@ -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);
|
||||
|
@ -35,7 +35,6 @@ class RenderNode;
|
||||
class Layer;
|
||||
class Matrix4;
|
||||
class SkiaColorFilter;
|
||||
class SkiaShader;
|
||||
class Patch;
|
||||
|
||||
enum DrawOpMode {
|
||||
@ -183,9 +182,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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
SkiaShader::SkiaShader(): mCaches(NULL) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SkiaShader::~SkiaShader() {
|
||||
}
|
||||
|
||||
void SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
|
||||
}
|
||||
|
||||
void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
|
||||
GLuint* textureUnit) {
|
||||
}
|
||||
|
||||
void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
|
||||
mCaches->bindTexture(texture->id);
|
||||
static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
|
||||
caches->bindTexture(texture->id);
|
||||
texture->setWrapST(wrapS, wrapT);
|
||||
}
|
||||
|
||||
void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
|
||||
screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
|
||||
screenSpace.multiply(modelView);
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
// The shader is not a gradient. Check for a bitmap shader.
|
||||
if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
|
||||
return kBitmap_SkiaShaderType;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (shader.asACustomShader(NULL)) {
|
||||
return kLayer_SkiaShaderType;
|
||||
}
|
||||
|
||||
return kNone_SkiaShaderType;
|
||||
}
|
||||
|
||||
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::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) {
|
||||
GLuint textureSlot = (*textureUnit)++;
|
||||
Caches::getInstance().activeTexture(textureSlot);
|
||||
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!");
|
||||
}
|
||||
|
||||
const float width = mLayer->getWidth();
|
||||
const float height = mLayer->getHeight();
|
||||
GLuint textureSlot = (*textureUnit)++;
|
||||
caches->activeTexture(textureSlot);
|
||||
|
||||
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);
|
||||
}
|
||||
struct BitmapShaderInfo {
|
||||
float width;
|
||||
float height;
|
||||
GLenum wrapS;
|
||||
GLenum wrapT;
|
||||
Texture* texture;
|
||||
};
|
||||
|
||||
SkiaShader* SkiaBitmapShader::copy() {
|
||||
SkiaBitmapShader* copy = new SkiaBitmapShader();
|
||||
copy->copyFrom(*this);
|
||||
copy->mBitmap = mBitmap;
|
||||
return copy;
|
||||
}
|
||||
|
||||
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;
|
||||
BitmapShaderInfo shaderInfo;
|
||||
if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Program* program = caches->currentProgram;
|
||||
Texture* texture = shaderInfo.texture;
|
||||
|
||||
const AutoTexture autoCleanup(texture);
|
||||
|
||||
const float width = texture->width;
|
||||
const float height = texture->height;
|
||||
|
||||
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);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Common gradient code
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updateLocalMatrix(matrix);
|
||||
|
||||
mIsSimple = count == 2;
|
||||
static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
|
||||
return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
|
||||
}
|
||||
|
||||
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
|
||||
void SkiaGradientShader::describe(Caches*, ProgramDescription& description,
|
||||
const Extensions& extensions, const SkShader& shader) {
|
||||
SkShader::GradientInfo gradInfo;
|
||||
gradInfo.fColorCount = 0;
|
||||
gradInfo.fColors = NULL;
|
||||
gradInfo.fColorOffsets = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void SkiaSweepGradientShader::describe(ProgramDescription& description,
|
||||
const Extensions& extensions) {
|
||||
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;
|
||||
description.isSimpleGradient = isSimpleGradient(gradInfo);
|
||||
}
|
||||
|
||||
void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
|
||||
const Snapshot& snapshot, GLuint* textureUnit) {
|
||||
if (CC_UNLIKELY(!mIsSimple)) {
|
||||
GLuint textureSlot = (*textureUnit)++;
|
||||
Caches::getInstance().activeTexture(textureSlot);
|
||||
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);
|
||||
|
||||
Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
|
||||
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->activeTexture(textureSlot);
|
||||
|
||||
#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
|
||||
|
@ -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
|
||||
};
|
||||
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);
|
||||
};
|
||||
|
||||
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;
|
||||
class InvalidSkiaShader {
|
||||
public:
|
||||
static void describe(Caches* caches, ProgramDescription& description,
|
||||
const Extensions& extensions, const SkShader& shader) {
|
||||
// This shader is unsupported. Skip it.
|
||||
}
|
||||
static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
|
||||
GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
|
||||
// This shader is unsupported. Skip it.
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
void updateLocalMatrix(const SkMatrix* matrix) {
|
||||
if (matrix) {
|
||||
mat4 localMatrix(*matrix);
|
||||
mShaderMatrix.loadInverse(localMatrix);
|
||||
} else {
|
||||
mShaderMatrix.loadIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
|
||||
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
|
||||
}; // class SkiaBitmapShader
|
||||
|
||||
/**
|
||||
* A shader that draws a linear gradient.
|
||||
* A shader that draws one of three types of gradient, depending on shader param.
|
||||
*/
|
||||
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);
|
||||
|
||||
private:
|
||||
SkiaLinearGradientShader() {
|
||||
}
|
||||
|
||||
bool mIsSimple;
|
||||
float* mBounds;
|
||||
uint32_t* mColors;
|
||||
float* mPositions;
|
||||
int mCount;
|
||||
}; // struct SkiaLinearGradientShader
|
||||
|
||||
/**
|
||||
* A shader that draws a sweep gradient.
|
||||
*/
|
||||
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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user