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