1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTextureStripAtlas.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContext.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContextPriv.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrProxyProvider.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrSurfaceContext.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGr.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPixelRef.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTSearch.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #define VALIDATE this->validate() 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #define VALIDATE 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrTextureStripAtlas::Hash : public SkTDynamicHash<GrTextureStripAtlas::AtlasEntry, 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrTextureStripAtlas::Desc> {}; 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint32_t GrTextureStripAtlas::gCacheCount = 0; 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrTextureStripAtlas::Hash* GrTextureStripAtlas::gAtlasCache = nullptr; 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrTextureStripAtlas::Hash* GrTextureStripAtlas::GetCache() { 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == gAtlasCache) { 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gAtlasCache = new Hash; 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return gAtlasCache; 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Remove the specified atlas from the cache 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::CleanUp(const GrContext*, void* info) { 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(info); 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AtlasEntry* entry = static_cast<AtlasEntry*>(info); 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // remove the cache entry 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GetCache()->remove(entry->fDesc); 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // remove the actual entry 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot delete entry; 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == GetCache()->count()) { 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot delete gAtlasCache; 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gAtlasCache = nullptr; 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrTextureStripAtlas* GrTextureStripAtlas::GetAtlas(const GrTextureStripAtlas::Desc& desc) { 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AtlasEntry* entry = GetCache()->find(desc); 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == entry) { 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry = new AtlasEntry; 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry->fAtlas = new GrTextureStripAtlas(desc); 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry->fDesc = desc; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fContext->addCleanUp(CleanUp, entry); 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GetCache()->add(entry); 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return entry->fAtlas; 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrTextureStripAtlas::GrTextureStripAtlas(GrTextureStripAtlas::Desc desc) 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fCacheKey(sk_atomic_inc(&gCacheCount)) 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLockedRows(0) 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fDesc(desc) 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fNumRows(desc.fHeight / desc.fRowHeight) 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fRows(new AtlasRow[fNumRows]) 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLRUFront(nullptr) 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLRUBack(nullptr) { 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fNumRows * fDesc.fRowHeight == fDesc.fHeight); 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->initLRU(); 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fNormalizedYHeight = SK_Scalar1 / fDesc.fHeight; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot VALIDATE; 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrTextureStripAtlas::~GrTextureStripAtlas() { delete[] fRows; } 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::lockRow(int row) { 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This should only be called on a row that is already locked. 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fRows[row].fLocks); 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRows[row].fLocks++; 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fLockedRows; 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint GrTextureStripAtlas::lockRow(const SkBitmap& bitmap) { 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot VALIDATE; 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == fLockedRows) { 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->lockTexture(); 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fTexContext) { 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return -1; 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int key = bitmap.getGenerationID(); 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int rowNumber = -1; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int index = this->searchByKey(key); 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (index >= 0) { 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We already have the data in a row, so we can just return that row 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AtlasRow* row = fKeyTable[index]; 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == row->fLocks) { 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->removeFromLRU(row); 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++row->fLocks; 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fLockedRows; 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Since all the rows are always stored in a contiguous array, we can save the memory 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // required for storing row numbers and just compute it with some pointer arithmetic 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rowNumber = static_cast<int>(row - fRows); 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // ~index is the index where we will insert the new key to keep things sorted 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot index = ~index; 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We don't have this data cached, so pick the least recently used row to copy into 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AtlasRow* row = this->getLRU(); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fLockedRows; 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == row) { 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // force a flush, which should unlock all the rows; then try again 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDesc.fContext->contextPriv().flush(nullptr); // tighten this up? 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row = this->getLRU(); 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == row) { 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --fLockedRows; 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return -1; 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->removeFromLRU(row); 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t oldKey = row->fKey; 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If we are writing into a row that already held bitmap data, we need to remove the 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // reference to that genID which is stored in our sorted table of key values. 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oldKey != kEmptyAtlasRowKey) { 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Find the entry in the list; if it's before the index where we plan on adding the new 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // entry, we decrement since it will shift elements ahead of it back by one. 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oldIndex = this->searchByKey(oldKey); 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oldIndex < index) { 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --index; 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fKeyTable.remove(oldIndex); 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row->fKey = key; 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row->fLocks = 1; 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fKeyTable.insert(index, 1, &row); 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rowNumber = static_cast<int>(row - fRows); 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(bitmap.width() == fDesc.fWidth); 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(bitmap.height() == fDesc.fRowHeight); 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Pass in the kDontFlush flag, since we know we're writing to a part of this texture 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // that is not currently in use 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTexContext->writePixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 0, rowNumber * fDesc.fRowHeight, 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrContextPriv::kDontFlush_PixelOpsFlag); 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(rowNumber >= 0); 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot VALIDATE; 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rowNumber; 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<GrTextureProxy> GrTextureStripAtlas::asTextureProxyRef() const { 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fTexContext->asTextureProxyRef(); 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::unlockRow(int row) { 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot VALIDATE; 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --fRows[row].fLocks; 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --fLockedRows; 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fRows[row].fLocks >= 0 && fLockedRows >= 0); 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == fRows[row].fLocks) { 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->appendLRU(fRows + row); 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == fLockedRows) { 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->unlockTexture(); 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot VALIDATE; 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrTextureStripAtlas::AtlasRow* GrTextureStripAtlas::getLRU() { 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Front is least-recently-used 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AtlasRow* row = fLRUFront; 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return row; 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::lockTexture() { 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrUniqueKey key; 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrUniqueKey::Builder builder(&key, kDomain, 1); 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot builder[0] = static_cast<uint32_t>(fCacheKey); 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot builder.finish(); 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrProxyProvider* proxyProvider = fDesc.fContext->contextPriv().proxyProvider(); 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey( 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot key, kTopLeft_GrSurfaceOrigin); 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!proxy) { 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrSurfaceDesc texDesc; 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot texDesc.fOrigin = kTopLeft_GrSurfaceOrigin; 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot texDesc.fWidth = fDesc.fWidth; 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot texDesc.fHeight = fDesc.fHeight; 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot texDesc.fConfig = fDesc.fConfig; 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proxy = proxyProvider->createProxy(texDesc, SkBackingFit::kExact, SkBudgeted::kYes, 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrResourceProvider::kNoPendingIO_Flag); 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!proxy) { 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin); 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proxyProvider->assignUniqueKeyToProxy(key, proxy.get()); 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is a new texture, so all of our cache info is now invalid 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->initLRU(); 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fKeyTable.rewind(); 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(proxy); 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTexContext = fDesc.fContext->contextPriv().makeWrappedSurfaceContext(std::move(proxy)); 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::unlockTexture() { 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fTexContext && 0 == fLockedRows); 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTexContext.reset(); 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::initLRU() { 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUFront = nullptr; 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUBack = nullptr; 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Initially all the rows are in the LRU list 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < fNumRows; ++i) { 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRows[i].fKey = kEmptyAtlasRowKey; 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRows[i].fNext = nullptr; 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRows[i].fPrev = nullptr; 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->appendLRU(fRows + i); 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr == fLRUFront || nullptr == fLRUFront->fPrev); 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr == fLRUBack || nullptr == fLRUBack->fNext); 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::appendLRU(AtlasRow* row) { 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr == row->fPrev && nullptr == row->fNext); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == fLRUFront && nullptr == fLRUBack) { 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUFront = row; 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUBack = row; 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row->fPrev = fLRUBack; 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUBack->fNext = row; 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUBack = row; 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::removeFromLRU(AtlasRow* row) { 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(row); 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (row->fNext && row->fPrev) { 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row->fPrev->fNext = row->fNext; 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row->fNext->fPrev = row->fPrev; 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == row->fNext) { 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(row == fLRUBack); 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUBack = row->fPrev; 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLRUBack) { 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUBack->fNext = nullptr; 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == row->fPrev) { 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(row == fLRUFront); 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUFront = row->fNext; 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLRUFront) { 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUFront->fPrev = nullptr; 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row->fNext = nullptr; 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot row->fPrev = nullptr; 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint GrTextureStripAtlas::searchByKey(uint32_t key) { 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AtlasRow target; 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot target.fKey = key; 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkTSearch<const AtlasRow, 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrTextureStripAtlas::KeyLess>((const AtlasRow**)fKeyTable.begin(), 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fKeyTable.count(), 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &target, 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sizeof(AtlasRow*)); 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrTextureStripAtlas::validate() { 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Our key table should be sorted 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t prev = 1 > fKeyTable.count() ? 0 : fKeyTable[0]->fKey; 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 1; i < fKeyTable.count(); ++i) { 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(prev < fKeyTable[i]->fKey); 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fKeyTable[i]->fKey != kEmptyAtlasRowKey); 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev = fKeyTable[i]->fKey; 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int lruCount = 0; 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Validate LRU pointers, and count LRU entries 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr == fLRUFront || nullptr == fLRUFront->fPrev); 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr == fLRUBack || nullptr == fLRUBack->fNext); 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (AtlasRow* r = fLRUFront; r != nullptr; r = r->fNext) { 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == r->fNext) { 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(r == fLRUBack); 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(r->fNext->fPrev == r); 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++lruCount; 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int rowLocks = 0; 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int freeRows = 0; 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < fNumRows; ++i) { 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rowLocks += fRows[i].fLocks; 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == fRows[i].fLocks) { 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++freeRows; 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool inLRU = false; 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Step through the LRU and make sure it's present 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (AtlasRow* r = fLRUFront; r != nullptr; r = r->fNext) { 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (r == &fRows[i]) { 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot inLRU = true; 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(inLRU); 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If we are locked, we should have a key 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(kEmptyAtlasRowKey != fRows[i].fKey); 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If we have a key != kEmptyAtlasRowKey, it should be in the key table 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fRows[i].fKey == kEmptyAtlasRowKey || this->searchByKey(fRows[i].fKey) >= 0); 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Our count of locks should equal the sum of row locks, unless we ran out of rows and flushed, 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // in which case we'll have one more lock than recorded in the rows (to represent the pending 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // lock of a row; which ensures we don't unlock the texture prematurely). 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(rowLocks == fLockedRows || rowLocks + 1 == fLockedRows); 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We should have one lru entry for each free row 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(freeRows == lruCount); 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If we have locked rows, we should have a locked texture, otherwise 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // it should be unlocked 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLockedRows == 0) { 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!fTexContext); 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fTexContext); 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 369