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