Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3083c3c9 authored by Lucas Crowthers's avatar Lucas Crowthers Committed by Gerrit Code Review
Browse files

core/jni/android/graphics: Cache copy of pre-scaled Bitmaps

Caching some pre-scaled Bitmap objects allows for optimizing later
scaling operations to reduce memory pressure.

CRs-fixed: 451681

Change-Id: Id4341e75911074ff9f565b2d386ccad8f3a223e8
parent c9b0de8a
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -354,6 +354,17 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
        SkCanvas canvas(*bitmap);
        canvas.scale(sx, sy);
        canvas.drawBitmap(*decoded, 0.0f, 0.0f, &paint);

        // Save off the unscaled version of bitmap to be used in later
        // transformations if it would reduce memory pressure. Only do
        // so if it is being upscaled more than 50%, is bigger than
        // 256x256, and not too big to be keeping a copy of (<1MB).
        const int numUnscaledPixels = decoded->width() * decoded->height();
        if (sx > 1.5 && numUnscaledPixels > 65536 && numUnscaledPixels < 262144) {
            bitmap->setUnscaledBitmap(decoded);
            adb2.detach(); //responsibility for freeing decoded's memory is
                           //transferred to bitmap's destructor
        }
    }

    if (padding) {
+20 −3
Original line number Diff line number Diff line
@@ -493,6 +493,7 @@ public:
                        jobject srcIRect, const SkRect& dst, SkPaint* paint,
                        jint screenDensity, jint bitmapDensity) {
        SkIRect    src, *srcPtr = NULL;
        SkPaint    filteredPaint;

        if (NULL != srcIRect) {
            GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
@@ -500,12 +501,28 @@ public:
        }

        if (screenDensity != 0 && screenDensity != bitmapDensity) {
            SkPaint filteredPaint;
            if (paint) {
                filteredPaint = *paint;
            }
            filteredPaint.setFilterBitmap(true);
            canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
            paint = &filteredPaint;
        }

        //If we're doing downscaling and we have an unscaled bitmap, convert
        //this to an upscaling operation, or at least less of a downscale
        SkBitmap*  unscaled = bitmap->unscaledBitmap();
        if (NULL != srcPtr && NULL != unscaled) {
            //use new bitmap and adapt the coordinates of the src rect to this new bitmap
            SkScalar   dx, dy;
            SkRect     srcF;
            dx = SkScalarDiv(SkIntToScalar(unscaled->width()), SkIntToScalar(bitmap->width()));
            dy = SkScalarDiv(SkIntToScalar(unscaled->height()), SkIntToScalar(bitmap->height()));
            srcF.set(SkScalarMul(SkIntToScalar(src.left()), dx),
                SkScalarMul(SkIntToScalar(src.top()), dy),
                SkScalarMul(SkIntToScalar(src.right()), dx),
                SkScalarMul(SkIntToScalar(src.bottom()), dy));

            canvas->drawBitmapScalarRect(*unscaled, &srcF, dst, paint);
        } else {
            canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
        }