Loading apct-tests/perftests/core/res/drawable-nodpi/fountain_night.jpg 0 → 100644 +3.41 MiB Loading image diff... apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -16,20 +16,29 @@ package android.graphics.perftests; import static org.junit.Assert.assertTrue; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Color; import android.graphics.ImageDecoder; import android.graphics.Paint; import android.graphics.RecordingCanvas; import android.graphics.RenderNode; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import androidx.test.InstrumentationRegistry; import androidx.test.filters.LargeTest; import com.android.perftests.core.R; import org.junit.Rule; import org.junit.Test; import java.io.IOException; @LargeTest public class CanvasPerfTest { @Rule Loading Loading @@ -93,4 +102,38 @@ public class CanvasPerfTest { node.end(canvas); } } @Test public void testCreateScaledBitmap() throws IOException { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final Context context = InstrumentationRegistry.getContext(); Bitmap source = ImageDecoder.decodeBitmap( ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night), (decoder, info, source1) -> { decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); source.setGainmap(null); while (state.keepRunning()) { Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) .recycle(); } } @Test public void testCreateScaledBitmapWithGainmap() throws IOException { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final Context context = InstrumentationRegistry.getContext(); Bitmap source = ImageDecoder.decodeBitmap( ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night), (decoder, info, source1) -> { decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); assertTrue(source.hasGainmap()); while (state.keepRunning()) { Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) .recycle(); } } } libs/hwui/SkiaCanvas.cpp +32 −2 Original line number Diff line number Diff line Loading @@ -588,10 +588,40 @@ void SkiaCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Pain // Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- bool SkiaCanvas::useGainmapShader(Bitmap& bitmap) { // If the bitmap doesn't have a gainmap, don't use the gainmap shader if (!bitmap.hasGainmap()) return false; // If we don't have an owned canvas, then we're either hardware accelerated or drawing // to a picture - use the gainmap shader out of caution. Ideally a picture canvas would // use a drawable here instead to defer making that decision until the last possible // moment if (!mCanvasOwned) return true; auto info = mCanvasOwned->imageInfo(); // If it's an unknown colortype then it's not a bitmap-backed canvas if (info.colorType() == SkColorType::kUnknown_SkColorType) return true; skcms_TransferFunction tfn; info.colorSpace()->transferFn(&tfn); auto transferType = skcms_TransferFunction_getType(&tfn); switch (transferType) { case skcms_TFType_HLGish: case skcms_TFType_HLGinvish: case skcms_TFType_PQish: return true; case skcms_TFType_Invalid: case skcms_TFType_sRGBish: return false; } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { auto image = bitmap.makeImage(); if (bitmap.hasGainmap()) { if (useGainmapShader(bitmap)) { Paint gainmapPaint = paint ? *paint : Paint(); sk_sp<SkShader> gainmapShader = uirenderer::MakeGainmapShader( image, bitmap.gainmap()->bitmap->makeImage(), bitmap.gainmap()->info, Loading @@ -618,7 +648,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); if (bitmap.hasGainmap()) { if (useGainmapShader(bitmap)) { Paint gainmapPaint = paint ? *paint : Paint(); sk_sp<SkShader> gainmapShader = uirenderer::MakeGainmapShader( image, bitmap.gainmap()->bitmap->makeImage(), bitmap.gainmap()->info, Loading libs/hwui/SkiaCanvas.h +2 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,8 @@ private: void drawPoints(const float* points, int count, const Paint& paint, SkCanvas::PointMode mode); bool useGainmapShader(Bitmap& bitmap); class Clip; std::unique_ptr<SkCanvas> mCanvasOwned; // Might own a canvas we allocated. Loading Loading
apct-tests/perftests/core/res/drawable-nodpi/fountain_night.jpg 0 → 100644 +3.41 MiB Loading image diff...
apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -16,20 +16,29 @@ package android.graphics.perftests; import static org.junit.Assert.assertTrue; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Color; import android.graphics.ImageDecoder; import android.graphics.Paint; import android.graphics.RecordingCanvas; import android.graphics.RenderNode; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import androidx.test.InstrumentationRegistry; import androidx.test.filters.LargeTest; import com.android.perftests.core.R; import org.junit.Rule; import org.junit.Test; import java.io.IOException; @LargeTest public class CanvasPerfTest { @Rule Loading Loading @@ -93,4 +102,38 @@ public class CanvasPerfTest { node.end(canvas); } } @Test public void testCreateScaledBitmap() throws IOException { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final Context context = InstrumentationRegistry.getContext(); Bitmap source = ImageDecoder.decodeBitmap( ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night), (decoder, info, source1) -> { decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); source.setGainmap(null); while (state.keepRunning()) { Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) .recycle(); } } @Test public void testCreateScaledBitmapWithGainmap() throws IOException { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final Context context = InstrumentationRegistry.getContext(); Bitmap source = ImageDecoder.decodeBitmap( ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night), (decoder, info, source1) -> { decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); assertTrue(source.hasGainmap()); while (state.keepRunning()) { Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) .recycle(); } } }
libs/hwui/SkiaCanvas.cpp +32 −2 Original line number Diff line number Diff line Loading @@ -588,10 +588,40 @@ void SkiaCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Pain // Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- bool SkiaCanvas::useGainmapShader(Bitmap& bitmap) { // If the bitmap doesn't have a gainmap, don't use the gainmap shader if (!bitmap.hasGainmap()) return false; // If we don't have an owned canvas, then we're either hardware accelerated or drawing // to a picture - use the gainmap shader out of caution. Ideally a picture canvas would // use a drawable here instead to defer making that decision until the last possible // moment if (!mCanvasOwned) return true; auto info = mCanvasOwned->imageInfo(); // If it's an unknown colortype then it's not a bitmap-backed canvas if (info.colorType() == SkColorType::kUnknown_SkColorType) return true; skcms_TransferFunction tfn; info.colorSpace()->transferFn(&tfn); auto transferType = skcms_TransferFunction_getType(&tfn); switch (transferType) { case skcms_TFType_HLGish: case skcms_TFType_HLGinvish: case skcms_TFType_PQish: return true; case skcms_TFType_Invalid: case skcms_TFType_sRGBish: return false; } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { auto image = bitmap.makeImage(); if (bitmap.hasGainmap()) { if (useGainmapShader(bitmap)) { Paint gainmapPaint = paint ? *paint : Paint(); sk_sp<SkShader> gainmapShader = uirenderer::MakeGainmapShader( image, bitmap.gainmap()->bitmap->makeImage(), bitmap.gainmap()->info, Loading @@ -618,7 +648,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); if (bitmap.hasGainmap()) { if (useGainmapShader(bitmap)) { Paint gainmapPaint = paint ? *paint : Paint(); sk_sp<SkShader> gainmapShader = uirenderer::MakeGainmapShader( image, bitmap.gainmap()->bitmap->makeImage(), bitmap.gainmap()->info, Loading
libs/hwui/SkiaCanvas.h +2 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,8 @@ private: void drawPoints(const float* points, int count, const Paint& paint, SkCanvas::PointMode mode); bool useGainmapShader(Bitmap& bitmap); class Clip; std::unique_ptr<SkCanvas> mCanvasOwned; // Might own a canvas we allocated. Loading