|  | /* | 
|  | * Copyright 2015 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "Test.h" | 
|  |  | 
|  | #include "SkMallocPixelRef.h" | 
|  | #include "SkPixelRef.h" | 
|  |  | 
|  | static void decrement_counter_proc(void* pixels, void* ctx) { | 
|  | int* counter = (int*)ctx; | 
|  | *counter -= 1; | 
|  | } | 
|  |  | 
|  | static void test_dont_leak_install(skiatest::Reporter* reporter) { | 
|  | bool success; | 
|  | int release_counter; | 
|  | SkImageInfo info; | 
|  | SkBitmap bm; | 
|  |  | 
|  | info = SkImageInfo::MakeN32Premul(0, 0); | 
|  | release_counter = 1; | 
|  | success = bm.installPixels(info, nullptr, 0, nullptr, decrement_counter_proc, &release_counter); | 
|  | REPORTER_ASSERT(reporter, true == success); | 
|  | bm.reset(); | 
|  | REPORTER_ASSERT(reporter, 0 == release_counter); | 
|  |  | 
|  | info = SkImageInfo::MakeN32Premul(10, 10); | 
|  | release_counter = 1; | 
|  | success = bm.installPixels(info, nullptr, 0, nullptr, decrement_counter_proc, &release_counter); | 
|  | REPORTER_ASSERT(reporter, true == success); | 
|  | bm.reset(); | 
|  | REPORTER_ASSERT(reporter, 0 == release_counter); | 
|  |  | 
|  | info = SkImageInfo::MakeN32Premul(-10, -10); | 
|  | release_counter = 1; | 
|  | success = bm.installPixels(info, nullptr, 0, nullptr, decrement_counter_proc, &release_counter); | 
|  | REPORTER_ASSERT(reporter, false == success); | 
|  | bm.reset(); | 
|  | REPORTER_ASSERT(reporter, 0 == release_counter); | 
|  | } | 
|  |  | 
|  | static void test_install(skiatest::Reporter* reporter) { | 
|  | bool success; | 
|  | SkImageInfo info = SkImageInfo::MakeN32Premul(0, 0); | 
|  | SkBitmap bm; | 
|  | // make sure we don't assert on an empty install | 
|  | success = bm.installPixels(info, nullptr, 0); | 
|  | REPORTER_ASSERT(reporter, success); | 
|  |  | 
|  | // no pixels should be the same as setInfo() | 
|  | info = SkImageInfo::MakeN32Premul(10, 10); | 
|  | success = bm.installPixels(info, nullptr, 0); | 
|  | REPORTER_ASSERT(reporter, success); | 
|  |  | 
|  | } | 
|  |  | 
|  | class TestListener : public SkPixelRef::GenIDChangeListener { | 
|  | public: | 
|  | explicit TestListener(int* ptr) : fPtr(ptr) {} | 
|  | void onChange() override { (*fPtr)++; } | 
|  | private: | 
|  | int* fPtr; | 
|  | }; | 
|  |  | 
|  | DEF_TEST(PixelRef_GenIDChange, r) { | 
|  | SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); | 
|  |  | 
|  | SkAutoTUnref<SkPixelRef> pixelRef(SkMallocPixelRef::NewAllocate(info, 0, nullptr)); | 
|  |  | 
|  | // Register a listener. | 
|  | int count = 0; | 
|  | pixelRef->addGenIDChangeListener(new TestListener(&count)); | 
|  | REPORTER_ASSERT(r, 0 == count); | 
|  |  | 
|  | // No one has looked at our pixelRef's generation ID, so invalidating it doesn't make sense. | 
|  | // (An SkPixelRef tree falls in the forest but there's nobody around to hear it.  Do we care?) | 
|  | pixelRef->notifyPixelsChanged(); | 
|  | REPORTER_ASSERT(r, 0 == count); | 
|  |  | 
|  | // Force the generation ID to be calculated. | 
|  | REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); | 
|  |  | 
|  | // Our listener was dropped in the first call to notifyPixelsChanged().  This is a no-op. | 
|  | pixelRef->notifyPixelsChanged(); | 
|  | REPORTER_ASSERT(r, 0 == count); | 
|  |  | 
|  | // Force the generation ID to be recalculated, then add a listener. | 
|  | REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); | 
|  | pixelRef->addGenIDChangeListener(new TestListener(&count)); | 
|  | pixelRef->notifyPixelsChanged(); | 
|  | REPORTER_ASSERT(r, 1 == count); | 
|  |  | 
|  | // Quick check that nullptr is safe. | 
|  | REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); | 
|  | pixelRef->addGenIDChangeListener(nullptr); | 
|  | pixelRef->notifyPixelsChanged(); | 
|  |  | 
|  | test_install(r); | 
|  | test_dont_leak_install(r); | 
|  | } |