17585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/*
27585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org * Copyright 2013 Google Inc.
37585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org *
47585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
57585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org * found in the LICENSE file.
67585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org */
77585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
87585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkBitmap.h"
98f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkCachingPixelRef.h"
107585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkCanvas.h"
117585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkData.h"
12ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com#include "SkDecodingImageGenerator.h"
132c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com#include "SkDiscardableMemoryPool.h"
147585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkImageDecoder.h"
152d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org#include "SkImageGeneratorPriv.h"
167585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkScaledImageCache.h"
177585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkStream.h"
182c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com#include "SkUtils.h"
196e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org
207585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "Test.h"
217585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
227585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
237585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org * Fill this bitmap with some color.
247585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org */
257585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic void make_test_image(SkBitmap* bm) {
266c22573edb234ad14df947278cfed010669a39a7reed    const int W = 50, H = 50;
276c22573edb234ad14df947278cfed010669a39a7reed    bm->allocN32Pixels(W, H);
287585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    bm->eraseColor(SK_ColorBLACK);
297585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkCanvas canvas(*bm);
307585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkPaint paint;
317585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    paint.setColor(SK_ColorBLUE);
327585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    canvas.drawRectCoords(0, 0, SkIntToScalar(W/2),
337585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                          SkIntToScalar(H/2), paint);
347585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    paint.setColor(SK_ColorWHITE);
357585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    canvas.drawRectCoords(SkIntToScalar(W/2), SkIntToScalar(H/2),
367585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                          SkIntToScalar(W), SkIntToScalar(H), paint);
377585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
387585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
397585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
407585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org * encode this bitmap into some data via SkImageEncoder
417585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org */
427585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic SkData* create_data_from_bitmap(const SkBitmap& bm,
437585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                       SkImageEncoder::Type type) {
447585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkDynamicMemoryWStream stream;
457585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) {
467585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return stream.copyToData();
477585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
487585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return NULL;
497585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
507585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
512c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
527585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
537585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic void compare_bitmaps(skiatest::Reporter* reporter,
547585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                            const SkBitmap& b1, const SkBitmap& b2,
557585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                            bool pixelPerfect = true) {
567585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.empty() == b2.empty());
577585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.width() == b2.width());
587585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.height() == b2.height());
597585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull());
607585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkAutoLockPixels autoLockPixels1(b1);
617585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkAutoLockPixels autoLockPixels2(b2);
627585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull());
637585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (b1.isNull() || b1.empty()) {
647585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
657585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
667585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, NULL != b1.getPixels());
677585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, NULL != b2.getPixels());
687585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if ((!(b1.getPixels())) || (!(b2.getPixels()))) {
697585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
707585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
717585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if ((b1.width() != b2.width()) ||
727585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        (b1.height() != b2.height())) {
737585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
747585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
757585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (!pixelPerfect) {
767585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
777585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
786e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org
797585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    int pixelErrors = 0;
807585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    for (int y = 0; y < b2.height(); ++y) {
817585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        for (int x = 0; x < b2.width(); ++x) {
827585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org            if (b1.getColor(x, y) != b2.getColor(x, y)) {
837585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                ++pixelErrors;
847585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org            }
857585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        }
867585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
877585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, 0 == pixelErrors);
887585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
897585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
9036d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.comtypedef bool (*InstallEncoded)(SkData* encoded, SkBitmap* dst);
9136d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com
927585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
9336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com   This function tests three differently encoded images against the
9436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com   original bitmap */
956e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.orgstatic void test_three_encodings(skiatest::Reporter* reporter,
9636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com                                 InstallEncoded install) {
977585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkBitmap original;
987585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    make_test_image(&original);
996e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    REPORTER_ASSERT(reporter, !original.empty());
1006e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    REPORTER_ASSERT(reporter, !original.isNull());
1016e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    if (original.empty() || original.isNull()) {
1026e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org        return;
1036e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    }
1047585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    static const SkImageEncoder::Type types[] = {
1057585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::kPNG_Type,
1067585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::kJPEG_Type,
1077585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::kWEBP_Type
1087585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    };
1097585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(types); i++) {
1107585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::Type type = types[i];
1117585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkAutoDataUnref encoded(create_data_from_bitmap(original, type));
1127585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        REPORTER_ASSERT(reporter, encoded.get() != NULL);
11336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        if (NULL == encoded.get()) {
11436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            continue;
11536d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        }
11636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        SkBitmap lazy;
11736d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        bool installSuccess = install(encoded.get(), &lazy);
11836d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        REPORTER_ASSERT(reporter, installSuccess);
11936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        if (!installSuccess) {
12036d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            continue;
1217585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        }
12236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        REPORTER_ASSERT(reporter, NULL == lazy.getPixels());
12336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        {
12436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            SkAutoLockPixels autoLockPixels(lazy);  // now pixels are good.
12536d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            REPORTER_ASSERT(reporter, NULL != lazy.getPixels());
12636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            if (NULL == lazy.getPixels()) {
12736d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com                continue;
12836d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            }
12936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        }
13036d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        // pixels should be gone!
13136d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        REPORTER_ASSERT(reporter, NULL == lazy.getPixels());
13236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        {
13336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            SkAutoLockPixels autoLockPixels(lazy);  // now pixels are good.
13436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            REPORTER_ASSERT(reporter, NULL != lazy.getPixels());
13536d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            if (NULL == lazy.getPixels()) {
13636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com                continue;
13736d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            }
13836d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        }
13936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        bool comparePixels = (SkImageEncoder::kPNG_Type == type);
14036d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        compare_bitmaps(reporter, original, lazy, comparePixels);
1416e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    }
1426e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org}
1437585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
14436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com////////////////////////////////////////////////////////////////////////////////
1452c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comstatic bool install_skCachingPixelRef(SkData* encoded, SkBitmap* dst) {
1462c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return SkCachingPixelRef::Install(
1473d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkDecodingImageGenerator::Create(
1483d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            encoded, SkDecodingImageGenerator::Options()), dst);
1496e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org}
1502c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comstatic bool install_skDiscardablePixelRef(SkData* encoded, SkBitmap* dst) {
1512c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // Use system-default discardable memory.
1523d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    return SkInstallDiscardablePixelRef(
1533d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkDecodingImageGenerator::Create(
1542d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org            encoded, SkDecodingImageGenerator::Options()), dst);
1556e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org}
1567585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
15736d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com////////////////////////////////////////////////////////////////////////////////
1586e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org/**
1592c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  This checks to see that a SkCachingPixelRef and a
1602c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  SkDiscardablePixelRef works as advertised with a
1612c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  SkDecodingImageGenerator.
1626e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org */
1632c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comDEF_TEST(DecodingImageGenerator, reporter) {
16436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com    test_three_encodings(reporter, install_skCachingPixelRef);
1652c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    test_three_encodings(reporter, install_skDiscardablePixelRef);
1667585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
167ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com
1682c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comclass TestImageGenerator : public SkImageGenerator {
1692c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.compublic:
1702c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    enum TestType {
1712c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        kFailGetInfo_TestType,
1722c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        kFailGetPixels_TestType,
1732c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        kSucceedGetPixels_TestType,
1742c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        kLast_TestType = kSucceedGetPixels_TestType
1752c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    };
1762c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    static int Width() { return 10; }
1772c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    static int Height() { return 10; }
1782c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    static SkColor Color() { return SK_ColorCYAN; }
1792c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    TestImageGenerator(TestType type, skiatest::Reporter* reporter)
1802c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        : fType(type), fReporter(reporter) {
1812c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkASSERT((fType <= kLast_TestType) && (fType >= 0));
1822c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
18358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    virtual ~TestImageGenerator() { }
18400f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org
18500f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.orgprotected:
18600f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
1872c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        REPORTER_ASSERT(fReporter, NULL != info);
1882c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        if ((NULL == info) || (kFailGetInfo_TestType == fType)) {
1892c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            return false;
1902c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
1912c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        info->fWidth = TestImageGenerator::Width();
1922c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        info->fHeight = TestImageGenerator::Height();
19328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        info->fColorType = kN32_SkColorType;
1942c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        info->fAlphaType = kOpaque_SkAlphaType;
1952c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return true;
1962c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
19700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org
19800f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    virtual bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
19900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org                             SkPMColor ctable[], int* ctableCount) SK_OVERRIDE {
2002c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        REPORTER_ASSERT(fReporter, pixels != NULL);
2012c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        size_t minRowBytes
2022c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            = static_cast<size_t>(info.fWidth * info.bytesPerPixel());
2032c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        REPORTER_ASSERT(fReporter, rowBytes >= minRowBytes);
2042c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        if ((NULL == pixels)
2052c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            || (fType != kSucceedGetPixels_TestType)
20628fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org            || (info.fColorType != kN32_SkColorType)) {
2072c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            return false;
2082c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
2092c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        char* bytePtr = static_cast<char*>(pixels);
2102c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        for (int y = 0; y < info.fHeight; ++y) {
2112c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            sk_memset32(reinterpret_cast<SkColor*>(bytePtr),
2122c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                        TestImageGenerator::Color(), info.fWidth);
2132c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            bytePtr += rowBytes;
2142c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
2152c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return true;
2162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2173d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
2182c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comprivate:
2192c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    const TestType fType;
2202c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    skiatest::Reporter* const fReporter;
2212c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com};
2223d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
22358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.orgstatic void check_test_image_generator_bitmap(skiatest::Reporter* reporter,
22458674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                                              const SkBitmap& bm) {
2252c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, TestImageGenerator::Width() == bm.width());
2262c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, TestImageGenerator::Height() == bm.height());
2272c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoLockPixels autoLockPixels(bm);
2282c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, NULL != bm.getPixels());
2292c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == bm.getPixels()) {
2302c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return;
2312c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2322c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    int errors = 0;
2332c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    for (int y = 0; y < bm.height(); ++y) {
2342c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        for (int x = 0; x < bm.width(); ++x) {
2352c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            if (TestImageGenerator::Color() != *bm.getAddr32(x, y)) {
2362c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                ++errors;
2372c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            }
2382c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
2392c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2402c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == errors);
2412c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2422c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
2432c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comenum PixelRefType {
2442c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    kSkCaching_PixelRefType,
2452c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    kSkDiscardable_PixelRefType,
2462c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    kLast_PixelRefType = kSkDiscardable_PixelRefType
2472c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com};
24858674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org
24958674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.orgstatic void check_pixelref(TestImageGenerator::TestType type,
25058674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                           skiatest::Reporter* reporter,
25158674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                           PixelRefType pixelRefType,
25258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                           SkDiscardableMemory::Factory* factory) {
2532c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT((pixelRefType >= 0) && (pixelRefType <= kLast_PixelRefType));
2542c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoTDelete<SkImageGenerator> gen(SkNEW_ARGS(TestImageGenerator,
2552c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                                                   (type, reporter)));
2562c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, gen.get() != NULL);
2572c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkBitmap lazy;
2582c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    bool success;
2592c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (kSkCaching_PixelRefType == pixelRefType) {
2602c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        // Ignore factory; use global SkScaledImageCache.
2612c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        success = SkCachingPixelRef::Install(gen.detach(), &lazy);
2622c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    } else {
263edd370f949a457f5d8f7a62efdaf685d4caf46fehalcanary@google.com        success = SkInstallDiscardablePixelRef(gen.detach(), &lazy, factory);
2642c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2652c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, success
2662c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                    == (TestImageGenerator::kFailGetInfo_TestType != type));
2672c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (TestImageGenerator::kSucceedGetPixels_TestType == type) {
26858674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org        check_test_image_generator_bitmap(reporter, lazy);
2692c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    } else if (TestImageGenerator::kFailGetPixels_TestType == type) {
2702c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkAutoLockPixels autoLockPixels(lazy);
2712c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        REPORTER_ASSERT(reporter, NULL == lazy.getPixels());
2722c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2732c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2741d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com
2751d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com// new/lock/delete is an odd pattern for a pixelref, but it needs to not assert
2761d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.comstatic void test_newlockdelete(skiatest::Reporter* reporter) {
2771d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkBitmap bm;
2781d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkImageGenerator* ig = new TestImageGenerator(
27958674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org        TestImageGenerator::kSucceedGetPixels_TestType, reporter);
2802d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org    SkInstallDiscardablePixelRef(ig, &bm);
2811d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    bm.pixelRef()->lockPixels();
2821d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com}
2831d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com
28436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com/**
2852c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  This tests the basic functionality of SkDiscardablePixelRef with a
2862c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  basic SkImageGenerator implementation and several
2872c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  SkDiscardableMemory::Factory choices.
28836d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com */
2892c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comDEF_TEST(DiscardableAndCachingPixelRef, reporter) {
2901d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    test_newlockdelete(reporter);
2911d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com
29258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetInfo_TestType,
29358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkCaching_PixelRefType, NULL);
29458674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
29558674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkCaching_PixelRefType, NULL);
29658674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
29758674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkCaching_PixelRefType, NULL);
2982c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
29958674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetInfo_TestType,
30058674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, NULL);
30158674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
30258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, NULL);
30358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
30458674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, NULL);
3052c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
3062c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoTUnref<SkDiscardableMemoryPool> pool(
307cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        SkDiscardableMemoryPool::Create(1, NULL));
3082c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
30958674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
31058674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, pool);
3112c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
31258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
31358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, pool);
3142c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
3152c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
3162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkDiscardableMemoryPool* globalPool = SkGetGlobalDiscardableMemoryPool();
317bc55eec80ef376208b3c1bfc65d8dc8b672d59f0halcanary@google.com    // Only acts differently from NULL on a platform that has a
318bc55eec80ef376208b3c1bfc65d8dc8b672d59f0halcanary@google.com    // default discardable memory implementation that differs from the
319bc55eec80ef376208b3c1bfc65d8dc8b672d59f0halcanary@google.com    // global DM pool.
32058674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
32158674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, globalPool);
32258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
32358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, globalPool);
324ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com}
325