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