1511923443facc611b3735b4688342c12071feaa0cdalton/* 2511923443facc611b3735b4688342c12071feaa0cdalton * Copyright 2014 Google Inc. 3511923443facc611b3735b4688342c12071feaa0cdalton * 4511923443facc611b3735b4688342c12071feaa0cdalton * Use of this source code is governed by a BSD-style license that can be 5511923443facc611b3735b4688342c12071feaa0cdalton * found in the LICENSE file. 6511923443facc611b3735b4688342c12071feaa0cdalton */ 7511923443facc611b3735b4688342c12071feaa0cdalton 8511923443facc611b3735b4688342c12071feaa0cdalton#if SK_SUPPORT_GPU 9511923443facc611b3735b4688342c12071feaa0cdalton 10511923443facc611b3735b4688342c12071feaa0cdalton#include "gl/GrGLNameAllocator.h" 11511923443facc611b3735b4688342c12071feaa0cdalton#include "Test.h" 12511923443facc611b3735b4688342c12071feaa0cdalton 13511923443facc611b3735b4688342c12071feaa0cdalton//////////////////////////////////////////////////////////////////////////////// 14511923443facc611b3735b4688342c12071feaa0cdalton 15511923443facc611b3735b4688342c12071feaa0cdaltonclass NameLeakTest { 16511923443facc611b3735b4688342c12071feaa0cdalton static const GrGLuint kFirstName = 101; 17511923443facc611b3735b4688342c12071feaa0cdalton static const GrGLuint kRange = 1013; 18511923443facc611b3735b4688342c12071feaa0cdalton 19511923443facc611b3735b4688342c12071feaa0cdaltonpublic: 20511923443facc611b3735b4688342c12071feaa0cdalton NameLeakTest(skiatest::Reporter* reporter) 21511923443facc611b3735b4688342c12071feaa0cdalton : fReporter(reporter), 22511923443facc611b3735b4688342c12071feaa0cdalton fAllocator(kFirstName, kFirstName + kRange), 23511923443facc611b3735b4688342c12071feaa0cdalton fAllocatedCount(0), 24511923443facc611b3735b4688342c12071feaa0cdalton fRandomName(kFirstName + 4 * kRange / 7) { 25511923443facc611b3735b4688342c12071feaa0cdalton memset(fAllocatedNames, 0, sizeof(fAllocatedNames)); 26511923443facc611b3735b4688342c12071feaa0cdalton } 27511923443facc611b3735b4688342c12071feaa0cdalton 28511923443facc611b3735b4688342c12071feaa0cdalton bool run() { 29511923443facc611b3735b4688342c12071feaa0cdalton if (!this->allocateAllRemaining()) { 30511923443facc611b3735b4688342c12071feaa0cdalton return false; 31511923443facc611b3735b4688342c12071feaa0cdalton } 32511923443facc611b3735b4688342c12071feaa0cdalton 33511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint freeCount = 1; freeCount <= kRange; ++freeCount) { 34511923443facc611b3735b4688342c12071feaa0cdalton if (!this->freeRandomNames(freeCount)) { 35511923443facc611b3735b4688342c12071feaa0cdalton return false; 36511923443facc611b3735b4688342c12071feaa0cdalton } 37511923443facc611b3735b4688342c12071feaa0cdalton if (!this->allocateAllRemaining()) { 38511923443facc611b3735b4688342c12071feaa0cdalton return false; 39511923443facc611b3735b4688342c12071feaa0cdalton } 40511923443facc611b3735b4688342c12071feaa0cdalton } 41511923443facc611b3735b4688342c12071feaa0cdalton 42511923443facc611b3735b4688342c12071feaa0cdalton return true; 43511923443facc611b3735b4688342c12071feaa0cdalton } 44511923443facc611b3735b4688342c12071feaa0cdalton 45511923443facc611b3735b4688342c12071feaa0cdaltonprivate: 46511923443facc611b3735b4688342c12071feaa0cdalton bool isAllocated(GrGLuint name) const { 47511923443facc611b3735b4688342c12071feaa0cdalton return fAllocatedNames[name - kFirstName]; 48511923443facc611b3735b4688342c12071feaa0cdalton } 49511923443facc611b3735b4688342c12071feaa0cdalton 50511923443facc611b3735b4688342c12071feaa0cdalton void setAllocated(GrGLuint name, bool allocated) { 51511923443facc611b3735b4688342c12071feaa0cdalton fAllocatedNames[name - kFirstName] = allocated; 52511923443facc611b3735b4688342c12071feaa0cdalton } 53511923443facc611b3735b4688342c12071feaa0cdalton 54511923443facc611b3735b4688342c12071feaa0cdalton bool allocateAllRemaining() { 55511923443facc611b3735b4688342c12071feaa0cdalton for (; fAllocatedCount < kRange; ++fAllocatedCount) { 56511923443facc611b3735b4688342c12071feaa0cdalton GrGLuint name = fAllocator.allocateName(); 57511923443facc611b3735b4688342c12071feaa0cdalton if (0 == name) { 58511923443facc611b3735b4688342c12071feaa0cdalton ERRORF(fReporter, 59511923443facc611b3735b4688342c12071feaa0cdalton "Name allocate failed, but there should still be %u free names", 60511923443facc611b3735b4688342c12071feaa0cdalton kRange - fAllocatedCount); 61511923443facc611b3735b4688342c12071feaa0cdalton return false; 62511923443facc611b3735b4688342c12071feaa0cdalton } 63511923443facc611b3735b4688342c12071feaa0cdalton if (name < kFirstName || name >= kFirstName + kRange) { 64511923443facc611b3735b4688342c12071feaa0cdalton ERRORF(fReporter, 65511923443facc611b3735b4688342c12071feaa0cdalton "Name allocate returned name %u outside its bounds [%u, %u)", 66511923443facc611b3735b4688342c12071feaa0cdalton name, kFirstName, kFirstName + kRange); 67511923443facc611b3735b4688342c12071feaa0cdalton return false; 68511923443facc611b3735b4688342c12071feaa0cdalton } 69511923443facc611b3735b4688342c12071feaa0cdalton if (this->isAllocated(name)) { 70511923443facc611b3735b4688342c12071feaa0cdalton ERRORF(fReporter, "Name allocate returned name that is already allocated"); 71511923443facc611b3735b4688342c12071feaa0cdalton return false; 72511923443facc611b3735b4688342c12071feaa0cdalton } 73511923443facc611b3735b4688342c12071feaa0cdalton 74511923443facc611b3735b4688342c12071feaa0cdalton this->setAllocated(name, true); 75511923443facc611b3735b4688342c12071feaa0cdalton } 76511923443facc611b3735b4688342c12071feaa0cdalton 77511923443facc611b3735b4688342c12071feaa0cdalton // Ensure it returns 0 once all the names are allocated. 78511923443facc611b3735b4688342c12071feaa0cdalton GrGLuint name = fAllocator.allocateName(); 79511923443facc611b3735b4688342c12071feaa0cdalton if (0 != name) { 80511923443facc611b3735b4688342c12071feaa0cdalton ERRORF(fReporter, 81511923443facc611b3735b4688342c12071feaa0cdalton "Name allocate did not fail when all names were already in use"); 82511923443facc611b3735b4688342c12071feaa0cdalton return false; 83511923443facc611b3735b4688342c12071feaa0cdalton } 84511923443facc611b3735b4688342c12071feaa0cdalton 85511923443facc611b3735b4688342c12071feaa0cdalton // Ensure every unique name is allocated. 86511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint i = 0; i < kRange; ++i) { 87511923443facc611b3735b4688342c12071feaa0cdalton if (!this->isAllocated(kFirstName + i)) { 88511923443facc611b3735b4688342c12071feaa0cdalton ERRORF(fReporter, "Not all unique names are allocated after allocateAllRemaining()"); 89511923443facc611b3735b4688342c12071feaa0cdalton return false; 90511923443facc611b3735b4688342c12071feaa0cdalton } 91511923443facc611b3735b4688342c12071feaa0cdalton } 92511923443facc611b3735b4688342c12071feaa0cdalton 93511923443facc611b3735b4688342c12071feaa0cdalton return true; 94511923443facc611b3735b4688342c12071feaa0cdalton } 95511923443facc611b3735b4688342c12071feaa0cdalton 96511923443facc611b3735b4688342c12071feaa0cdalton bool freeRandomNames(GrGLuint count) { 97511923443facc611b3735b4688342c12071feaa0cdalton // The values a and c make up an LCG (pseudo-random generator). These 98511923443facc611b3735b4688342c12071feaa0cdalton // values must satisfy the Hull-Dobell Theorem (with m=kRange): 99511923443facc611b3735b4688342c12071feaa0cdalton // http://en.wikipedia.org/wiki/Linear_congruential_generator 100511923443facc611b3735b4688342c12071feaa0cdalton // We use our own generator to guarantee it hits each unique value 101511923443facc611b3735b4688342c12071feaa0cdalton // within kRange exactly once before repeating. 102511923443facc611b3735b4688342c12071feaa0cdalton const GrGLuint seed = (count + fRandomName) / 2; 103511923443facc611b3735b4688342c12071feaa0cdalton const GrGLuint a = seed * kRange + 1; 104511923443facc611b3735b4688342c12071feaa0cdalton const GrGLuint c = (seed * 743) % kRange; 105511923443facc611b3735b4688342c12071feaa0cdalton 106511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint i = 0; i < count; ++i) { 107511923443facc611b3735b4688342c12071feaa0cdalton fRandomName = (a * fRandomName + c) % kRange; 108511923443facc611b3735b4688342c12071feaa0cdalton const GrGLuint name = kFirstName + fRandomName; 109511923443facc611b3735b4688342c12071feaa0cdalton if (!this->isAllocated(name)) { 110511923443facc611b3735b4688342c12071feaa0cdalton ERRORF(fReporter, "Test bug: Should not free a not-allocated name at this point (%u)", i); 111511923443facc611b3735b4688342c12071feaa0cdalton return false; 112511923443facc611b3735b4688342c12071feaa0cdalton } 113511923443facc611b3735b4688342c12071feaa0cdalton 114511923443facc611b3735b4688342c12071feaa0cdalton fAllocator.free(name); 115511923443facc611b3735b4688342c12071feaa0cdalton this->setAllocated(name, false); 116511923443facc611b3735b4688342c12071feaa0cdalton --fAllocatedCount; 117511923443facc611b3735b4688342c12071feaa0cdalton } 118511923443facc611b3735b4688342c12071feaa0cdalton 119511923443facc611b3735b4688342c12071feaa0cdalton return true; 120511923443facc611b3735b4688342c12071feaa0cdalton } 121511923443facc611b3735b4688342c12071feaa0cdalton 122511923443facc611b3735b4688342c12071feaa0cdalton skiatest::Reporter* fReporter; 123511923443facc611b3735b4688342c12071feaa0cdalton GrGLNameAllocator fAllocator; 124511923443facc611b3735b4688342c12071feaa0cdalton bool fAllocatedNames[kRange]; 125511923443facc611b3735b4688342c12071feaa0cdalton GrGLuint fAllocatedCount; 126511923443facc611b3735b4688342c12071feaa0cdalton GrGLuint fRandomName; 127511923443facc611b3735b4688342c12071feaa0cdalton}; 128511923443facc611b3735b4688342c12071feaa0cdalton 129511923443facc611b3735b4688342c12071feaa0cdaltonDEF_GPUTEST(NameAllocator, reporter, factory) { 130511923443facc611b3735b4688342c12071feaa0cdalton // Ensure no names are leaked or double-allocated during heavy usage. 131511923443facc611b3735b4688342c12071feaa0cdalton { 132511923443facc611b3735b4688342c12071feaa0cdalton NameLeakTest nameLeakTest(reporter); 133511923443facc611b3735b4688342c12071feaa0cdalton nameLeakTest.run(); 134511923443facc611b3735b4688342c12071feaa0cdalton } 135511923443facc611b3735b4688342c12071feaa0cdalton 136511923443facc611b3735b4688342c12071feaa0cdalton static const GrGLuint range = 32; 137511923443facc611b3735b4688342c12071feaa0cdalton GrGLNameAllocator allocator(1, 1 + range); 138511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint i = 1; i <= range; ++i) { 139511923443facc611b3735b4688342c12071feaa0cdalton allocator.allocateName(); 140511923443facc611b3735b4688342c12071feaa0cdalton } 141511923443facc611b3735b4688342c12071feaa0cdalton REPORTER_ASSERT(reporter, 0 == allocator.allocateName()); 142511923443facc611b3735b4688342c12071feaa0cdalton 143511923443facc611b3735b4688342c12071feaa0cdalton // Test freeing names out of range. 144511923443facc611b3735b4688342c12071feaa0cdalton allocator.free(allocator.firstName() - 1); 145511923443facc611b3735b4688342c12071feaa0cdalton allocator.free(allocator.endName()); 146511923443facc611b3735b4688342c12071feaa0cdalton REPORTER_ASSERT(reporter, 0 == allocator.allocateName()); 147511923443facc611b3735b4688342c12071feaa0cdalton 148511923443facc611b3735b4688342c12071feaa0cdalton // Test freeing not-allocated names. 149511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint i = 1; i <= range/2; i += 2) { 150511923443facc611b3735b4688342c12071feaa0cdalton allocator.free(i); 151511923443facc611b3735b4688342c12071feaa0cdalton } 152511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint i = 1; i <= range/2; i += 2) { 153511923443facc611b3735b4688342c12071feaa0cdalton // None of these names will be allocated. 154511923443facc611b3735b4688342c12071feaa0cdalton allocator.free(i); 155511923443facc611b3735b4688342c12071feaa0cdalton } 156511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint i = 1; i <= range/2; ++i) { 157511923443facc611b3735b4688342c12071feaa0cdalton // Every other name will not be be allocated. 158511923443facc611b3735b4688342c12071feaa0cdalton allocator.free(i); 159511923443facc611b3735b4688342c12071feaa0cdalton } 160511923443facc611b3735b4688342c12071feaa0cdalton for (GrGLuint i = 1; i <= range/2; ++i) { 161511923443facc611b3735b4688342c12071feaa0cdalton if (0 == allocator.allocateName()) { 162511923443facc611b3735b4688342c12071feaa0cdalton ERRORF(reporter, "Name allocate failed when there should be free names"); 163511923443facc611b3735b4688342c12071feaa0cdalton break; 164511923443facc611b3735b4688342c12071feaa0cdalton } 165511923443facc611b3735b4688342c12071feaa0cdalton } 166511923443facc611b3735b4688342c12071feaa0cdalton REPORTER_ASSERT(reporter, 0 == allocator.allocateName()); 167511923443facc611b3735b4688342c12071feaa0cdalton} 168511923443facc611b3735b4688342c12071feaa0cdalton 169511923443facc611b3735b4688342c12071feaa0cdalton#endif 170