2021-05-20 13:45:10 +00:00
|
|
|
// 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
|
2021-06-10 14:57:16 +00:00
|
|
|
constexpr int kInvalidMat = 0;
|
|
|
|
constexpr int kSolidMat = 1;
|
|
|
|
constexpr int kLinearMat = 2;
|
|
|
|
constexpr int kRadialMat = 3;
|
2021-05-20 13:45:10 +00:00
|
|
|
|
|
|
|
class SortKey {
|
|
|
|
public:
|
2021-05-24 18:41:24 +00:00
|
|
|
// 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.
|
2021-05-20 13:45:10 +00:00
|
|
|
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;
|
|
|
|
|
2021-06-17 19:34:15 +00:00
|
|
|
static const uint32_t kTransparentShift = kNumMaterialBits + kNumDepthBits;
|
2021-05-20 13:45:10 +00:00
|
|
|
static const uint32_t kNumTransparentBits = 1;
|
|
|
|
static const uint32_t kTransparentMask = (0x1 << kNumTransparentBits) - 1;
|
|
|
|
|
2021-05-24 18:41:24 +00:00
|
|
|
// 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)
|
2021-05-20 13:45:10 +00:00
|
|
|
SortKey() : fKey((kMaxDepth - 1) << kMaterialShift) {}
|
2021-06-17 19:34:15 +00:00
|
|
|
explicit SortKey(bool transparent, uint32_t depth, uint32_t material) {
|
|
|
|
SkASSERT(depth != 0 /* && material != 0*/);
|
2021-05-20 13:45:10 +00:00
|
|
|
SkASSERT(!(depth & ~kDepthMask));
|
|
|
|
SkASSERT(!(material & ~kMaterialMask));
|
|
|
|
|
2021-05-24 18:41:24 +00:00
|
|
|
// TODO: better encapsulate the reversal of the depth & material when the key is opaque
|
2021-05-20 13:45:10 +00:00
|
|
|
if (transparent) {
|
2021-05-24 18:41:24 +00:00
|
|
|
fKey = (0x1 << kTransparentShift) |
|
|
|
|
(depth & kDepthMask) << kDepthShift |
|
|
|
|
(material & kMaterialMask) << kMaterialShift;
|
2021-05-20 13:45:10 +00:00
|
|
|
} else {
|
2021-05-24 18:41:24 +00:00
|
|
|
SkASSERT(kNumDepthBits == kNumMaterialBits);
|
|
|
|
|
|
|
|
uint32_t munged;
|
2021-05-20 13:45:10 +00:00
|
|
|
// We want the opaque draws to be sorted front to back
|
|
|
|
munged = kMaxDepth - depth - 1;
|
2021-05-24 18:41:24 +00:00
|
|
|
SkASSERT(!(munged & ~kDepthMask));
|
2021-05-20 13:45:10 +00:00
|
|
|
|
2021-06-17 19:34:15 +00:00
|
|
|
fKey = (munged & kDepthMask) << kMaterialShift |
|
2021-05-20 13:45:10 +00:00
|
|
|
(material & kMaterialMask) << kDepthShift;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool transparent() const {
|
|
|
|
return (fKey >> kTransparentShift) & kTransparentMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t depth() const {
|
|
|
|
if (this->transparent()) {
|
|
|
|
return (fKey >> kDepthShift) & kDepthMask;
|
|
|
|
}
|
|
|
|
|
2021-06-17 19:34:15 +00:00
|
|
|
// TODO: better encapsulate the reversal of the depth & material when the key is opaque
|
2021-05-20 13:45:10 +00:00
|
|
|
uint32_t tmp = (fKey >> kMaterialShift) & kDepthMask;
|
|
|
|
return (kMaxDepth - tmp) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t material() const {
|
2021-05-24 18:41:24 +00:00
|
|
|
// TODO: better encapsulate the reversal of the depth & material when the key is opaque
|
2021-05-20 13:45:10 +00:00
|
|
|
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
|