1 // Copyright 2021 Google LLC. 2 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3 4 #ifndef SortKey_DEFINED 5 #define SortKey_DEFINED 6 7 #include "include/core/SkTypes.h" 8 9 // These are the material IDs that are stored in the sort key for each class of material 10 constexpr int kInvalidMat = 0; 11 constexpr int kSolidMat = 1; 12 constexpr int kLinearMat = 2; 13 constexpr int kRadialMat = 3; 14 15 class SortKey { 16 public: 17 // field: | transparent | clipID | depth | material | 18 // bits: | 1 | 8 | 4 | 4 | 19 // Note: the depth and material fields are swapped when the key is opaque and the depth's 20 // order is reversed. This forces all opaque draws with the be sorted by material first 21 // and then front to back. Transparent draws will continue to be sorted back to front. 22 static const uint32_t kMaterialShift = 0; 23 static const uint32_t kNumMaterialBits = 4; 24 static const uint32_t kMaterialMask = (0x1 << kNumMaterialBits) - 1; 25 26 // The pseudo-Z generated by the draw calls is just a proxy for painter's order. 27 // The "depth" value stored here is a munged version of the pseudo-Z to get the sorting 28 // correct. 29 // For opaque objects the pseudo-Z is reversed so opaque objects are drawn front to back (i.e., 30 // reverse painter's order). 31 // For transparent objects the pseudo-Z is untouched but the transparent bit is set on the 32 // key so transparent object will always be drawn after the opaque objects and in painter's 33 // order. 34 static const uint32_t kDepthShift = kNumMaterialBits; 35 static const uint32_t kNumDepthBits = 4; 36 static const uint32_t kDepthMask = (0x1 << kNumDepthBits) - 1; 37 static const uint32_t kMaxDepth = kDepthMask; 38 39 static const uint32_t kTransparentShift = kNumMaterialBits + kNumDepthBits; 40 static const uint32_t kNumTransparentBits = 1; 41 static const uint32_t kTransparentMask = (0x1 << kNumTransparentBits) - 1; 42 43 // TODO: make it clearer that we're initializing the default depth to be 0 here (since the 44 // default key is opaque, its sense is flipped) SortKey()45 SortKey() : fKey((kMaxDepth - 1) << kMaterialShift) {} SortKey(bool transparent,uint32_t depth,uint32_t material)46 explicit SortKey(bool transparent, uint32_t depth, uint32_t material) { 47 SkASSERT(depth != 0 /* && material != 0*/); 48 SkASSERT(!(depth & ~kDepthMask)); 49 SkASSERT(!(material & ~kMaterialMask)); 50 51 // TODO: better encapsulate the reversal of the depth & material when the key is opaque 52 if (transparent) { 53 fKey = (0x1 << kTransparentShift) | 54 (depth & kDepthMask) << kDepthShift | 55 (material & kMaterialMask) << kMaterialShift; 56 } else { 57 SkASSERT(kNumDepthBits == kNumMaterialBits); 58 59 uint32_t munged; 60 // We want the opaque draws to be sorted front to back 61 munged = kMaxDepth - depth - 1; 62 SkASSERT(!(munged & ~kDepthMask)); 63 64 fKey = (munged & kDepthMask) << kMaterialShift | 65 (material & kMaterialMask) << kDepthShift; 66 } 67 } 68 transparent()69 bool transparent() const { 70 return (fKey >> kTransparentShift) & kTransparentMask; 71 } 72 depth()73 uint32_t depth() const { 74 if (this->transparent()) { 75 return (fKey >> kDepthShift) & kDepthMask; 76 } 77 78 // TODO: better encapsulate the reversal of the depth & material when the key is opaque 79 uint32_t tmp = (fKey >> kMaterialShift) & kDepthMask; 80 return (kMaxDepth - tmp) - 1; 81 } 82 material()83 uint32_t material() const { 84 // TODO: better encapsulate the reversal of the depth & material when the key is opaque 85 if (this->transparent()) { 86 return (fKey >> kMaterialShift) & kMaterialMask; 87 } else { 88 return (fKey >> kDepthShift) & kMaterialMask; 89 } 90 } 91 dump()92 void dump() const { 93 SkDebugf("transparent: %d depth: %d mat: %d\n", 94 this->transparent(), 95 this->depth(), 96 this->material()); 97 } 98 99 bool operator>(const SortKey& other) const { return fKey > other.fKey; } 100 bool operator<(const SortKey& other) const { return fKey < other.fKey; } 101 102 private: 103 uint64_t fKey; 104 }; 105 106 #endif // Key_DEFINED 107