1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2014 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 #ifndef skgpu_RectanizerPow2_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define skgpu_RectanizerPow2_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkMathPriv.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkIPoint16.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Rectanizer.h" 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu { 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker // This Rectanizer quantizes the incoming rects to powers of 2. Each power 22*c8dee2aaSAndroid Build Coastguard Worker // of two can have, at most, one active row/shelf. Once a row/shelf for 23*c8dee2aaSAndroid Build Coastguard Worker // a particular power of two gets full its fRows entry is recycled to point 24*c8dee2aaSAndroid Build Coastguard Worker // to a new row. 25*c8dee2aaSAndroid Build Coastguard Worker // The skyline algorithm almost always provides a better packing. 26*c8dee2aaSAndroid Build Coastguard Worker // 27*c8dee2aaSAndroid Build Coastguard Worker // Mark this class final in an effort to avoid the vtable when this subclass is used explicitly. 28*c8dee2aaSAndroid Build Coastguard Worker class RectanizerPow2 final : public Rectanizer { 29*c8dee2aaSAndroid Build Coastguard Worker public: RectanizerPow2(int w,int h)30*c8dee2aaSAndroid Build Coastguard Worker RectanizerPow2(int w, int h) : Rectanizer(w, h) { 31*c8dee2aaSAndroid Build Coastguard Worker this->reset(); 32*c8dee2aaSAndroid Build Coastguard Worker } 33*c8dee2aaSAndroid Build Coastguard Worker ~RectanizerPow2()34*c8dee2aaSAndroid Build Coastguard Worker ~RectanizerPow2() final {} 35*c8dee2aaSAndroid Build Coastguard Worker reset()36*c8dee2aaSAndroid Build Coastguard Worker void reset() final { 37*c8dee2aaSAndroid Build Coastguard Worker fNextStripY = 0; 38*c8dee2aaSAndroid Build Coastguard Worker fAreaSoFar = 0; 39*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(fRows, sizeof(fRows)); 40*c8dee2aaSAndroid Build Coastguard Worker } 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard Worker bool addRect(int w, int h, SkIPoint16* loc) final; 43*c8dee2aaSAndroid Build Coastguard Worker percentFull()44*c8dee2aaSAndroid Build Coastguard Worker float percentFull() const final { 45*c8dee2aaSAndroid Build Coastguard Worker return fAreaSoFar / ((float)this->width() * this->height()); 46*c8dee2aaSAndroid Build Coastguard Worker } 47*c8dee2aaSAndroid Build Coastguard Worker 48*c8dee2aaSAndroid Build Coastguard Worker private: 49*c8dee2aaSAndroid Build Coastguard Worker static const int kMIN_HEIGHT_POW2 = 2; 50*c8dee2aaSAndroid Build Coastguard Worker static const int kMaxExponent = 16; 51*c8dee2aaSAndroid Build Coastguard Worker 52*c8dee2aaSAndroid Build Coastguard Worker struct Row { 53*c8dee2aaSAndroid Build Coastguard Worker SkIPoint16 fLoc; 54*c8dee2aaSAndroid Build Coastguard Worker // fRowHeight is actually known by this struct's position in fRows 55*c8dee2aaSAndroid Build Coastguard Worker // but it is used to signal if there exists an open row of this height 56*c8dee2aaSAndroid Build Coastguard Worker int fRowHeight; 57*c8dee2aaSAndroid Build Coastguard Worker canAddWidthRow58*c8dee2aaSAndroid Build Coastguard Worker bool canAddWidth(int width, int containerWidth) const { 59*c8dee2aaSAndroid Build Coastguard Worker return fLoc.fX + width <= containerWidth; 60*c8dee2aaSAndroid Build Coastguard Worker } 61*c8dee2aaSAndroid Build Coastguard Worker }; 62*c8dee2aaSAndroid Build Coastguard Worker 63*c8dee2aaSAndroid Build Coastguard Worker Row fRows[kMaxExponent]; // 0-th entry will be unused 64*c8dee2aaSAndroid Build Coastguard Worker 65*c8dee2aaSAndroid Build Coastguard Worker int fNextStripY; 66*c8dee2aaSAndroid Build Coastguard Worker int32_t fAreaSoFar; 67*c8dee2aaSAndroid Build Coastguard Worker HeightToRowIndex(int height)68*c8dee2aaSAndroid Build Coastguard Worker static int HeightToRowIndex(int height) { 69*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(height >= kMIN_HEIGHT_POW2); 70*c8dee2aaSAndroid Build Coastguard Worker int index = 32 - SkCLZ(height - 1); 71*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(index < kMaxExponent); 72*c8dee2aaSAndroid Build Coastguard Worker return index; 73*c8dee2aaSAndroid Build Coastguard Worker } 74*c8dee2aaSAndroid Build Coastguard Worker canAddStrip(int height)75*c8dee2aaSAndroid Build Coastguard Worker bool canAddStrip(int height) const { 76*c8dee2aaSAndroid Build Coastguard Worker return fNextStripY + height <= this->height(); 77*c8dee2aaSAndroid Build Coastguard Worker } 78*c8dee2aaSAndroid Build Coastguard Worker initRow(Row * row,int rowHeight)79*c8dee2aaSAndroid Build Coastguard Worker void initRow(Row* row, int rowHeight) { 80*c8dee2aaSAndroid Build Coastguard Worker row->fLoc.set(0, fNextStripY); 81*c8dee2aaSAndroid Build Coastguard Worker row->fRowHeight = rowHeight; 82*c8dee2aaSAndroid Build Coastguard Worker fNextStripY += rowHeight; 83*c8dee2aaSAndroid Build Coastguard Worker } 84*c8dee2aaSAndroid Build Coastguard Worker }; 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker } // End of namespace skgpu 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker #endif 89