OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 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 #include "Test.h" |
| 8 |
| 9 #include "SkCanvas.h" |
| 10 #include "SkRasterCanvasLayerAllocator.h" |
| 11 |
| 12 #include <unordered_map> |
| 13 |
| 14 class TestAllocator : public SkRasterCanvasLayerAllocator { |
| 15 public: |
| 16 TestAllocator() : fAllocationCount (0) { } |
| 17 ~TestAllocator() override { |
| 18 for (int i = 0; i < fAllocationCount; i++) { |
| 19 delete [] fBuffers[i]; |
| 20 } |
| 21 } |
| 22 |
| 23 void* getNativeContext(void* buffer, |
| 24 const SkMatrix& transform, |
| 25 const SkIRect& clip_bounds) override; |
| 26 |
| 27 protected: |
| 28 void* allocateLayer(const SkImageInfo& info, |
| 29 size_t* rowBytes, |
| 30 void (**deallocator)(void*), |
| 31 void** deallocatorPayload, |
| 32 void* initialData) override; |
| 33 typedef std::unordered_map<void*, int*> context_map_t; |
| 34 context_map_t fContexts; |
| 35 |
| 36 public: |
| 37 int fAllocationCount; |
| 38 char* fBuffers[10]; |
| 39 int fContextSentinel[10]; |
| 40 }; |
| 41 |
| 42 bool sDeallocated = false; |
| 43 |
| 44 void TestDeallocator (void* payload) { |
| 45 sDeallocated = true; |
| 46 } |
| 47 |
| 48 void* TestAllocator::getNativeContext(void* buffer, |
| 49 const SkMatrix& transform, |
| 50 const SkIRect& clip_bounds) { |
| 51 context_map_t::iterator it = fContexts.find(buffer); |
| 52 if (it == fContexts.end()) { |
| 53 //SkDebugf("native context not found"); |
| 54 return nullptr; |
| 55 } |
| 56 //SkDebugf("native context %lx", it->second); |
| 57 return it->second; |
| 58 } |
| 59 |
| 60 void* TestAllocator::allocateLayer(const SkImageInfo& info, |
| 61 size_t* rowBytes, |
| 62 void (**deallocator)(void*), |
| 63 void** deallocatorPayload, |
| 64 void* initialData) { |
| 65 char* buffer = new char [info.height() * info.minRowBytes()]; |
| 66 fBuffers[fAllocationCount] = buffer; |
| 67 int* context = &fContextSentinel[fAllocationCount]; |
| 68 // Some parts of Skia will fill in the correct value if |
| 69 // you pass 0, but then that information is lost before |
| 70 // we get to allocating pixel refs. |
| 71 *rowBytes = info.minRowBytes(); |
| 72 *deallocator = TestDeallocator; |
| 73 *deallocatorPayload = buffer; |
| 74 fAllocationCount++; |
| 75 fContexts.insert({buffer, context}); |
| 76 return buffer; |
| 77 } |
| 78 |
| 79 void should_use_slot(skiatest::Reporter* reporter, |
| 80 SkCanvas* canvas, |
| 81 TestAllocator* allocator, |
| 82 SkIRect bounds, |
| 83 int i) { |
| 84 SkMatrix m = SkMatrix::I(); |
| 85 void* buffer = canvas->accessTopLayerPixels(nullptr, nullptr); |
| 86 REPORTER_ASSERT(reporter, allocator->fAllocationCount >= i); |
| 87 REPORTER_ASSERT(reporter, buffer == allocator->fBuffers[i]); |
| 88 REPORTER_ASSERT(reporter, allocator->getNativeContext(buffer, m, bounds) == |
| 89 &allocator->fContextSentinel[i]); |
| 90 } |
| 91 |
| 92 DEF_TEST(TestSaveAndRestore, reporter) { |
| 93 TestAllocator* allocator = new TestAllocator; |
| 94 |
| 95 SkIRect bounds = SkIRect::MakeWH(20, 20); |
| 96 SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.size()); |
| 97 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| 98 |
| 99 // The result of createCanvas() uses memory and context provided by |
| 100 // the allocator. |
| 101 sk_sp<SkCanvas> canvas = allocator->createCanvas(info, props); |
| 102 REPORTER_ASSERT(reporter, canvas); |
| 103 should_use_slot(reporter, canvas.get(), allocator, bounds, 0); |
| 104 |
| 105 // After saveLayer() we've made another allocation and it's backing |
| 106 // the bitmap. |
| 107 canvas->saveLayer(nullptr, nullptr); |
| 108 should_use_slot(reporter, canvas.get(), allocator, bounds, 1); |
| 109 REPORTER_ASSERT(reporter, !sDeallocated); |
| 110 |
| 111 // After restore(), the deallocator callback has been triggered and the |
| 112 // previous buffer and context are now active. |
| 113 canvas->restore(); |
| 114 REPORTER_ASSERT(reporter, sDeallocated); |
| 115 should_use_slot(reporter, canvas.get(), allocator, bounds, 0); |
| 116 |
| 117 // Multiple saves continue to allocate (or reuse) buffers & contexts. |
| 118 |
| 119 canvas->saveLayer(nullptr, nullptr); |
| 120 int latestIndex = allocator->fAllocationCount - 1; |
| 121 should_use_slot(reporter, canvas.get(), allocator, bounds, latestIndex); |
| 122 |
| 123 canvas->saveLayer(nullptr, nullptr); |
| 124 int previousIndex = latestIndex; |
| 125 latestIndex = allocator->fAllocationCount - 1; |
| 126 should_use_slot(reporter, canvas.get(), allocator, bounds, latestIndex); |
| 127 |
| 128 // Even after several saves and restores, restore backs us up the stack. |
| 129 canvas->restore(); |
| 130 should_use_slot(reporter, canvas.get(), allocator, bounds, previousIndex); |
| 131 canvas->restore(); |
| 132 should_use_slot(reporter, canvas.get(), allocator, bounds, 0); |
| 133 } |
| 134 |
| 135 DEF_TEST(TestInitialData, reporter) { |
| 136 |
| 137 } |
| 138 |
| 139 |
| 140 |
OLD | NEW |