1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tests/Test.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkMallocPixelRef.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPixelRef.h" 12cb93a386Sopenharmony_ci#include "include/private/SkIDChangeListener.h" 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_cistatic void decrement_counter_proc(void* pixels, void* ctx) { 15cb93a386Sopenharmony_ci int* counter = (int*)ctx; 16cb93a386Sopenharmony_ci *counter -= 1; 17cb93a386Sopenharmony_ci} 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cistatic void test_dont_leak_install(skiatest::Reporter* reporter) { 20cb93a386Sopenharmony_ci bool success; 21cb93a386Sopenharmony_ci int release_counter; 22cb93a386Sopenharmony_ci SkImageInfo info; 23cb93a386Sopenharmony_ci SkBitmap bm; 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci info = SkImageInfo::MakeN32Premul(0, 0); 26cb93a386Sopenharmony_ci release_counter = 1; 27cb93a386Sopenharmony_ci success = bm.installPixels(info, nullptr, 0, decrement_counter_proc, &release_counter); 28cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, true == success); 29cb93a386Sopenharmony_ci bm.reset(); 30cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == release_counter); 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci info = SkImageInfo::MakeN32Premul(10, 10); 33cb93a386Sopenharmony_ci release_counter = 1; 34cb93a386Sopenharmony_ci success = bm.installPixels(info, nullptr, 0, decrement_counter_proc, &release_counter); 35cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, true == success); 36cb93a386Sopenharmony_ci bm.reset(); 37cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == release_counter); 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci info = SkImageInfo::MakeN32Premul(-10, -10); 40cb93a386Sopenharmony_ci release_counter = 1; 41cb93a386Sopenharmony_ci success = bm.installPixels(info, nullptr, 0, decrement_counter_proc, &release_counter); 42cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false == success); 43cb93a386Sopenharmony_ci bm.reset(); 44cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == release_counter); 45cb93a386Sopenharmony_ci} 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_cistatic void test_install(skiatest::Reporter* reporter) { 48cb93a386Sopenharmony_ci bool success; 49cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeN32Premul(0, 0); 50cb93a386Sopenharmony_ci SkBitmap bm; 51cb93a386Sopenharmony_ci // make sure we don't assert on an empty install 52cb93a386Sopenharmony_ci success = bm.installPixels(info, nullptr, 0); 53cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, success); 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci // no pixels should be the same as setInfo() 56cb93a386Sopenharmony_ci info = SkImageInfo::MakeN32Premul(10, 10); 57cb93a386Sopenharmony_ci success = bm.installPixels(info, nullptr, 0); 58cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, success); 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci} 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ciclass TestListener : public SkIDChangeListener { 63cb93a386Sopenharmony_cipublic: 64cb93a386Sopenharmony_ci explicit TestListener(int* ptr) : fPtr(ptr) {} 65cb93a386Sopenharmony_ci void changed() override { (*fPtr)++; } 66cb93a386Sopenharmony_ciprivate: 67cb93a386Sopenharmony_ci int* fPtr; 68cb93a386Sopenharmony_ci}; 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ciDEF_TEST(PixelRef_GenIDChange, r) { 71cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci sk_sp<SkPixelRef> pixelRef = SkMallocPixelRef::MakeAllocate(info, 0); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci // Register a listener. 76cb93a386Sopenharmony_ci int count = 0; 77cb93a386Sopenharmony_ci pixelRef->addGenIDChangeListener(sk_make_sp<TestListener>(&count)); 78cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 == count); 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci // No one has looked at our pixelRef's generation ID, so invalidating it doesn't make sense. 81cb93a386Sopenharmony_ci // (An SkPixelRef tree falls in the forest but there's nobody around to hear it. Do we care?) 82cb93a386Sopenharmony_ci pixelRef->notifyPixelsChanged(); 83cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 == count); 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci // Force the generation ID to be calculated. 86cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci // Our listener was dropped in the first call to notifyPixelsChanged(). This is a no-op. 89cb93a386Sopenharmony_ci pixelRef->notifyPixelsChanged(); 90cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 == count); 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci // Force the generation ID to be recalculated, then add a listener. 93cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); 94cb93a386Sopenharmony_ci pixelRef->addGenIDChangeListener(sk_make_sp<TestListener>(&count)); 95cb93a386Sopenharmony_ci pixelRef->notifyPixelsChanged(); 96cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 1 == count); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci // Check that asking for deregistration causes the listener to not be called. 99cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); 100cb93a386Sopenharmony_ci auto listener = sk_make_sp<TestListener>(&count); 101cb93a386Sopenharmony_ci pixelRef->addGenIDChangeListener(listener); 102cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 1 == count); 103cb93a386Sopenharmony_ci listener->markShouldDeregister(); 104cb93a386Sopenharmony_ci pixelRef->notifyPixelsChanged(); 105cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 1 == count); 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci // Check that we use deregistration to prevent unbounded growth. 108cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); 109cb93a386Sopenharmony_ci listener = sk_make_sp<TestListener>(&count); 110cb93a386Sopenharmony_ci pixelRef->addGenIDChangeListener(listener); 111cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 1 == count); 112cb93a386Sopenharmony_ci listener->markShouldDeregister(); 113cb93a386Sopenharmony_ci // Add second listener. Should deregister first listener. 114cb93a386Sopenharmony_ci pixelRef->addGenIDChangeListener(sk_make_sp<TestListener>(&count)); 115cb93a386Sopenharmony_ci REPORTER_ASSERT(r, listener->unique()); 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci // Quick check that nullptr is safe. 118cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID()); 119cb93a386Sopenharmony_ci pixelRef->addGenIDChangeListener(nullptr); 120cb93a386Sopenharmony_ci pixelRef->notifyPixelsChanged(); 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci test_install(r); 123cb93a386Sopenharmony_ci test_dont_leak_install(r); 124cb93a386Sopenharmony_ci} 125