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"
122c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com#include "SkDiscardableMemoryPool.h"
137585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkImageDecoder.h"
142d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org#include "SkImageGeneratorPriv.h"
15011f39aeb2b9715546eb74d9ebb71be7baf95fdereed#include "SkResourceCache.h"
167585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "SkStream.h"
172c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com#include "SkUtils.h"
186e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org
197585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org#include "Test.h"
207585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
217585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
227585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org * Fill this bitmap with some color.
237585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org */
247585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic void make_test_image(SkBitmap* bm) {
256c22573edb234ad14df947278cfed010669a39a7reed    const int W = 50, H = 50;
266c22573edb234ad14df947278cfed010669a39a7reed    bm->allocN32Pixels(W, H);
277585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    bm->eraseColor(SK_ColorBLACK);
287585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkCanvas canvas(*bm);
297585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkPaint paint;
307585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    paint.setColor(SK_ColorBLUE);
317585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    canvas.drawRectCoords(0, 0, SkIntToScalar(W/2),
327585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                          SkIntToScalar(H/2), paint);
337585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    paint.setColor(SK_ColorWHITE);
347585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    canvas.drawRectCoords(SkIntToScalar(W/2), SkIntToScalar(H/2),
357585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                          SkIntToScalar(W), SkIntToScalar(H), paint);
367585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
377585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
387585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
397585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org * encode this bitmap into some data via SkImageEncoder
407585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org */
417585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic SkData* create_data_from_bitmap(const SkBitmap& bm,
427585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                                       SkImageEncoder::Type type) {
437585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkDynamicMemoryWStream stream;
447585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) {
457585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return stream.copyToData();
467585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
477585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    return NULL;
487585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
497585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
502c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
517585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
527585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.orgstatic void compare_bitmaps(skiatest::Reporter* reporter,
537585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                            const SkBitmap& b1, const SkBitmap& b2,
547585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                            bool pixelPerfect = true) {
557585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.empty() == b2.empty());
567585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.width() == b2.width());
577585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.height() == b2.height());
587585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull());
597585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkAutoLockPixels autoLockPixels1(b1);
607585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkAutoLockPixels autoLockPixels2(b2);
617585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull());
627585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (b1.isNull() || b1.empty()) {
637585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
647585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
6549f085dddff10473b6ebf832a974288300224e60bsalomon    REPORTER_ASSERT(reporter, b1.getPixels());
6649f085dddff10473b6ebf832a974288300224e60bsalomon    REPORTER_ASSERT(reporter, b2.getPixels());
677585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if ((!(b1.getPixels())) || (!(b2.getPixels()))) {
687585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
697585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
707585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if ((b1.width() != b2.width()) ||
717585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        (b1.height() != b2.height())) {
727585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
737585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
747585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    if (!pixelPerfect) {
757585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        return;
767585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
776e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org
787585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    int pixelErrors = 0;
797585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    for (int y = 0; y < b2.height(); ++y) {
807585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        for (int x = 0; x < b2.width(); ++x) {
817585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org            if (b1.getColor(x, y) != b2.getColor(x, y)) {
827585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org                ++pixelErrors;
837585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org            }
847585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        }
857585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    }
867585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    REPORTER_ASSERT(reporter, 0 == pixelErrors);
877585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
887585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
8936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.comtypedef bool (*InstallEncoded)(SkData* encoded, SkBitmap* dst);
9036d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com
917585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org/**
9236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com   This function tests three differently encoded images against the
9336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com   original bitmap */
946e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.orgstatic void test_three_encodings(skiatest::Reporter* reporter,
9536d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com                                 InstallEncoded install) {
967585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    SkBitmap original;
977585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    make_test_image(&original);
986e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    REPORTER_ASSERT(reporter, !original.empty());
996e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    REPORTER_ASSERT(reporter, !original.isNull());
1006e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    if (original.empty() || original.isNull()) {
1016e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org        return;
1026e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    }
1037585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    static const SkImageEncoder::Type types[] = {
1047585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::kPNG_Type,
1057585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::kJPEG_Type,
1067585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::kWEBP_Type
1077585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    };
1087585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(types); i++) {
1097585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkImageEncoder::Type type = types[i];
1107585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        SkAutoDataUnref encoded(create_data_from_bitmap(original, type));
1117585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        REPORTER_ASSERT(reporter, encoded.get() != NULL);
11236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        if (NULL == encoded.get()) {
11336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            continue;
11436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        }
11536d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        SkBitmap lazy;
11636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        bool installSuccess = install(encoded.get(), &lazy);
11736d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        REPORTER_ASSERT(reporter, installSuccess);
11836d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        if (!installSuccess) {
11936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            continue;
1207585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org        }
12136d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        REPORTER_ASSERT(reporter, NULL == lazy.getPixels());
12236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        {
12336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            SkAutoLockPixels autoLockPixels(lazy);  // now pixels are good.
12449f085dddff10473b6ebf832a974288300224e60bsalomon            REPORTER_ASSERT(reporter, lazy.getPixels());
12536d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            if (NULL == lazy.getPixels()) {
12636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com                continue;
12736d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            }
12836d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        }
12936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        // pixels should be gone!
13036d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        REPORTER_ASSERT(reporter, NULL == lazy.getPixels());
13136d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        {
13236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            SkAutoLockPixels autoLockPixels(lazy);  // now pixels are good.
13349f085dddff10473b6ebf832a974288300224e60bsalomon            REPORTER_ASSERT(reporter, lazy.getPixels());
13436d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            if (NULL == lazy.getPixels()) {
13536d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com                continue;
13636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com            }
13736d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        }
13836d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        bool comparePixels = (SkImageEncoder::kPNG_Type == type);
13936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com        compare_bitmaps(reporter, original, lazy, comparePixels);
1406e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org    }
1416e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org}
1427585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
14336d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com////////////////////////////////////////////////////////////////////////////////
1442c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comstatic bool install_skCachingPixelRef(SkData* encoded, SkBitmap* dst) {
1455965c8ae4ee960275da4bc40189bdba85aab8b5ereed    return SkCachingPixelRef::Install(SkImageGenerator::NewFromData(encoded), dst);
1466e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org}
1472c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comstatic bool install_skDiscardablePixelRef(SkData* encoded, SkBitmap* dst) {
1482c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // Use system-default discardable memory.
1495965c8ae4ee960275da4bc40189bdba85aab8b5ereed    return SkInstallDiscardablePixelRef(encoded, dst);
1506e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org}
1517585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org
15236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com////////////////////////////////////////////////////////////////////////////////
1536e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org/**
1542c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  This checks to see that a SkCachingPixelRef and a
1552c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  SkDiscardablePixelRef works as advertised with a
1562c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  SkDecodingImageGenerator.
1576e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org */
1582c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comDEF_TEST(DecodingImageGenerator, reporter) {
15936d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com    test_three_encodings(reporter, install_skCachingPixelRef);
1602c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    test_three_encodings(reporter, install_skDiscardablePixelRef);
1617585479202f1fe0b6a0a9dcd27697b56154706f4commit-bot@chromium.org}
162ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com
1632c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comclass TestImageGenerator : public SkImageGenerator {
1642c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.compublic:
1652c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    enum TestType {
1662c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        kFailGetPixels_TestType,
1672c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        kSucceedGetPixels_TestType,
1682c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        kLast_TestType = kSucceedGetPixels_TestType
1692c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    };
1702c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    static int Width() { return 10; }
1712c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    static int Height() { return 10; }
172ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary    static uint32_t Color() { return 0xff123456; }
1732c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    TestImageGenerator(TestType type, skiatest::Reporter* reporter)
1743ef71e343bf075888fb50892350390b4dd47de24reed    : INHERITED(GetMyInfo()), fType(type), fReporter(reporter) {
1752c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkASSERT((fType <= kLast_TestType) && (fType >= 0));
1762c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
17758674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    virtual ~TestImageGenerator() { }
17800f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org
17900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.orgprotected:
1803ef71e343bf075888fb50892350390b4dd47de24reed    static SkImageInfo GetMyInfo() {
1813ef71e343bf075888fb50892350390b4dd47de24reed        return SkImageInfo::MakeN32(TestImageGenerator::Width(), TestImageGenerator::Height(),
1823ef71e343bf075888fb50892350390b4dd47de24reed                                    kOpaque_SkAlphaType);
1833ef71e343bf075888fb50892350390b4dd47de24reed    }
1843ef71e343bf075888fb50892350390b4dd47de24reed
18587fa631969e0bdbee3c0845aa2b9bf35b9b82eb0scroggo    virtual Result onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
1869552662e9fee5eb0ef435e52ab9db505d7ebe4adscroggo                               const Options&,
18736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                               SkPMColor ctable[], int* ctableCount) override {
1882c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        REPORTER_ASSERT(fReporter, pixels != NULL);
1890864908ca50049d3d907fc5c3749bc8a436b4738scroggo        REPORTER_ASSERT(fReporter, rowBytes >= info.minRowBytes());
1900864908ca50049d3d907fc5c3749bc8a436b4738scroggo        if (fType != kSucceedGetPixels_TestType) {
1910864908ca50049d3d907fc5c3749bc8a436b4738scroggo            return kUnimplemented;
1920864908ca50049d3d907fc5c3749bc8a436b4738scroggo        }
1930864908ca50049d3d907fc5c3749bc8a436b4738scroggo        if (info.colorType() != kN32_SkColorType) {
1940864908ca50049d3d907fc5c3749bc8a436b4738scroggo            return kInvalidConversion;
1952c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
1962c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        char* bytePtr = static_cast<char*>(pixels);
197e5ea500d4714a7d84de2bf913e81be3b65d2de68reed        for (int y = 0; y < info.height(); ++y) {
1982c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            sk_memset32(reinterpret_cast<SkColor*>(bytePtr),
199e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                        TestImageGenerator::Color(), info.width());
2002c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            bytePtr += rowBytes;
2012c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
2020864908ca50049d3d907fc5c3749bc8a436b4738scroggo        return kSuccess;
2032c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2043d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
2052c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comprivate:
2062c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    const TestType fType;
2072c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    skiatest::Reporter* const fReporter;
2083ef71e343bf075888fb50892350390b4dd47de24reed
2093ef71e343bf075888fb50892350390b4dd47de24reed    typedef SkImageGenerator INHERITED;
2102c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com};
2113d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
21258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.orgstatic void check_test_image_generator_bitmap(skiatest::Reporter* reporter,
21358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                                              const SkBitmap& bm) {
2142c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, TestImageGenerator::Width() == bm.width());
2152c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, TestImageGenerator::Height() == bm.height());
2162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoLockPixels autoLockPixels(bm);
21749f085dddff10473b6ebf832a974288300224e60bsalomon    REPORTER_ASSERT(reporter, bm.getPixels());
2182c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == bm.getPixels()) {
2192c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return;
2202c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2212c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    int errors = 0;
2222c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    for (int y = 0; y < bm.height(); ++y) {
2232c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        for (int x = 0; x < bm.width(); ++x) {
2242c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            if (TestImageGenerator::Color() != *bm.getAddr32(x, y)) {
2252c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                ++errors;
2262c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            }
2272c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
2282c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2292c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == errors);
2302c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2312c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
2322c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comenum PixelRefType {
2332c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    kSkCaching_PixelRefType,
2342c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    kSkDiscardable_PixelRefType,
2352c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    kLast_PixelRefType = kSkDiscardable_PixelRefType
2362c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com};
23758674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org
23858674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.orgstatic void check_pixelref(TestImageGenerator::TestType type,
23958674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                           skiatest::Reporter* reporter,
24058674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                           PixelRefType pixelRefType,
24158674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                           SkDiscardableMemory::Factory* factory) {
2422c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT((pixelRefType >= 0) && (pixelRefType <= kLast_PixelRefType));
2432c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoTDelete<SkImageGenerator> gen(SkNEW_ARGS(TestImageGenerator,
2442c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                                                   (type, reporter)));
2452c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, gen.get() != NULL);
2462c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkBitmap lazy;
2472c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    bool success;
2482c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (kSkCaching_PixelRefType == pixelRefType) {
249011f39aeb2b9715546eb74d9ebb71be7baf95fdereed        // Ignore factory; use global cache.
2502c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        success = SkCachingPixelRef::Install(gen.detach(), &lazy);
2512c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    } else {
252edd370f949a457f5d8f7a62efdaf685d4caf46fehalcanary@google.com        success = SkInstallDiscardablePixelRef(gen.detach(), &lazy, factory);
2532c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2543ef71e343bf075888fb50892350390b4dd47de24reed    REPORTER_ASSERT(reporter, success);
2552c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (TestImageGenerator::kSucceedGetPixels_TestType == type) {
25658674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org        check_test_image_generator_bitmap(reporter, lazy);
2572c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    } else if (TestImageGenerator::kFailGetPixels_TestType == type) {
2582c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkAutoLockPixels autoLockPixels(lazy);
2592c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        REPORTER_ASSERT(reporter, NULL == lazy.getPixels());
2602c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2612c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2621d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com
2631d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com// new/lock/delete is an odd pattern for a pixelref, but it needs to not assert
2641d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.comstatic void test_newlockdelete(skiatest::Reporter* reporter) {
2651d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkBitmap bm;
2661d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkImageGenerator* ig = new TestImageGenerator(
26758674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org        TestImageGenerator::kSucceedGetPixels_TestType, reporter);
2682d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org    SkInstallDiscardablePixelRef(ig, &bm);
2691d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    bm.pixelRef()->lockPixels();
2701d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com}
2711d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com
27236d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com/**
2732c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  This tests the basic functionality of SkDiscardablePixelRef with a
2742c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  basic SkImageGenerator implementation and several
2752c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *  SkDiscardableMemory::Factory choices.
27636d08c5c90c7607cd559769f7a9c2b3364eeba85halcanary@google.com */
2772c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comDEF_TEST(DiscardableAndCachingPixelRef, reporter) {
2781d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    test_newlockdelete(reporter);
2791d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com
28058674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
28158674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkCaching_PixelRefType, NULL);
28258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
28358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkCaching_PixelRefType, NULL);
2842c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
28558674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
28658674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, NULL);
28758674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
28858674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, NULL);
2892c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
2902c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoTUnref<SkDiscardableMemoryPool> pool(
291cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        SkDiscardableMemoryPool::Create(1, NULL));
2922c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
29358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
29458674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, pool);
2952c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
29658674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
29758674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, pool);
2982c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
2992c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
3002c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkDiscardableMemoryPool* globalPool = SkGetGlobalDiscardableMemoryPool();
301bc55eec80ef376208b3c1bfc65d8dc8b672d59f0halcanary@google.com    // Only acts differently from NULL on a platform that has a
302bc55eec80ef376208b3c1bfc65d8dc8b672d59f0halcanary@google.com    // default discardable memory implementation that differs from the
303bc55eec80ef376208b3c1bfc65d8dc8b672d59f0halcanary@google.com    // global DM pool.
30458674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
30558674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, globalPool);
30658674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org    check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType,
30758674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.org                   reporter, kSkDiscardable_PixelRefType, globalPool);
308ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com}
309ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary
310ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary////////////////////////////////////////////////////////////////////////////////
311ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary
312ea4673fde65f15d6f1ca77e24ced7348c4914517halcanaryDEF_TEST(Image_NewFromGenerator, r) {
313ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary    TestImageGenerator::TestType testTypes[] = {
314ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        TestImageGenerator::kFailGetPixels_TestType,
315ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        TestImageGenerator::kSucceedGetPixels_TestType,
316ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary    };
317ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary    for (size_t i = 0; i < SK_ARRAY_COUNT(testTypes); ++i) {
318ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        TestImageGenerator::TestType test = testTypes[i];
319ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        SkImageGenerator* gen = SkNEW_ARGS(TestImageGenerator, (test, r));
320ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        SkAutoTUnref<SkImage> image(SkImage::NewFromGenerator(gen));
321ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        if (NULL == image.get()) {
322ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary            ERRORF(r, "SkImage::NewFromGenerator unexpecedly failed ["
323ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary                   SK_SIZE_T_SPECIFIER "]", i);
324ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary            continue;
325ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        }
326ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        REPORTER_ASSERT(r, TestImageGenerator::Width() == image->width());
327ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        REPORTER_ASSERT(r, TestImageGenerator::Height() == image->height());
328ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary
329ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        SkBitmap bitmap;
330848250415eddc54075f7eb8795e8db79e749c6abreed        bitmap.allocN32Pixels(TestImageGenerator::Width(), TestImageGenerator::Height());
331ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        SkCanvas canvas(bitmap);
332ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        const SkColor kDefaultColor = 0xffabcdef;
333ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        canvas.clear(kDefaultColor);
334b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr        canvas.drawImage(image, 0, 0, NULL);
335ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        if (TestImageGenerator::kSucceedGetPixels_TestType == test) {
336ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary            REPORTER_ASSERT(
337ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary                    r, TestImageGenerator::Color() == *bitmap.getAddr32(0, 0));
338ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        } else {
339ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary            REPORTER_ASSERT(r, kDefaultColor == bitmap.getColor(0,0));
340ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary        }
341ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary    }
342ea4673fde65f15d6f1ca77e24ced7348c4914517halcanary}
343