blob: 7bf14ef009fe333a835982d1c02c23b5488de236 [file] [log] [blame]
// Copyright 2021 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#ifndef SortKey_DEFINED
#define SortKey_DEFINED
#include "include/core/SkTypes.h"
// These are the material IDs that are stored in the sort key for each class of material
constexpr int kInvalidMat = 0;
constexpr int kSolidMat = 1;
constexpr int kLinearMat = 2;
constexpr int kRadialMat = 3;
class SortKey {
public:
// field: | transparent | clipID | depth | material |
// bits: | 1 | 8 | 4 | 4 |
// Note: the depth and material fields are swapped when the key is opaque and the depth's
// order is reversed. This forces all opaque draws with the be sorted by material first
// and then front to back. Transparent draws will continue to be sorted back to front.
static const uint32_t kMaterialShift = 0;
static const uint32_t kNumMaterialBits = 4;
static const uint32_t kMaterialMask = (0x1 << kNumMaterialBits) - 1;
// The pseudo-Z generated by the draw calls is just a proxy for painter's order.
// The "depth" value stored here is a munged version of the pseudo-Z to get the sorting
// correct.
// For opaque objects the pseudo-Z is reversed so opaque objects are drawn front to back (i.e.,
// reverse painter's order).
// For transparent objects the pseudo-Z is untouched but the transparent bit is set on the
// key so transparent object will always be drawn after the opaque objects and in painter's
// order.
static const uint32_t kDepthShift = kNumMaterialBits;
static const uint32_t kNumDepthBits = 4;
static const uint32_t kDepthMask = (0x1 << kNumDepthBits) - 1;
static const uint32_t kMaxDepth = kDepthMask;
static const uint32_t kTransparentShift = kNumMaterialBits + kNumDepthBits;
static const uint32_t kNumTransparentBits = 1;
static const uint32_t kTransparentMask = (0x1 << kNumTransparentBits) - 1;
// TODO: make it clearer that we're initializing the default depth to be 0 here (since the
// default key is opaque, its sense is flipped)
SortKey() : fKey((kMaxDepth - 1) << kMaterialShift) {}
explicit SortKey(bool transparent, uint32_t depth, uint32_t material) {
SkASSERT(depth != 0 /* && material != 0*/);
SkASSERT(!(depth & ~kDepthMask));
SkASSERT(!(material & ~kMaterialMask));
// TODO: better encapsulate the reversal of the depth & material when the key is opaque
if (transparent) {
fKey = (0x1 << kTransparentShift) |
(depth & kDepthMask) << kDepthShift |
(material & kMaterialMask) << kMaterialShift;
} else {
SkASSERT(kNumDepthBits == kNumMaterialBits);
uint32_t munged;
// We want the opaque draws to be sorted front to back
munged = kMaxDepth - depth - 1;
SkASSERT(!(munged & ~kDepthMask));
fKey = (munged & kDepthMask) << kMaterialShift |
(material & kMaterialMask) << kDepthShift;
}
}
bool transparent() const {
return (fKey >> kTransparentShift) & kTransparentMask;
}
uint32_t depth() const {
if (this->transparent()) {
return (fKey >> kDepthShift) & kDepthMask;
}
// TODO: better encapsulate the reversal of the depth & material when the key is opaque
uint32_t tmp = (fKey >> kMaterialShift) & kDepthMask;
return (kMaxDepth - tmp) - 1;
}
uint32_t material() const {
// TODO: better encapsulate the reversal of the depth & material when the key is opaque
if (this->transparent()) {
return (fKey >> kMaterialShift) & kMaterialMask;
} else {
return (fKey >> kDepthShift) & kMaterialMask;
}
}
void dump() const {
SkDebugf("transparent: %d depth: %d mat: %d\n",
this->transparent(),
this->depth(),
this->material());
}
bool operator>(const SortKey& other) const { return fKey > other.fKey; }
bool operator<(const SortKey& other) const { return fKey < other.fKey; }
private:
uint64_t fKey;
};
#endif // Key_DEFINED