// 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 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 kClipShift = kNumMaterialBits + kNumDepthBits;
    static const uint32_t kNumClipBits = 8;
    static const uint32_t kClipMask = (0x01 << kNumClipBits) - 1;
    static const uint32_t kMaxClipID = kClipMask;

    static const uint32_t kTransparentShift = kNumMaterialBits + kNumDepthBits + kNumClipBits;
    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 clipID, uint32_t depth, uint32_t material) {
        SkASSERT(clipID != 0 && depth != 0 /* && material != 0*/);
        SkASSERT(!(clipID & ~kClipMask));
        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) |
                   (clipID & kClipMask) << kClipShift |
                   (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 = (clipID & kClipMask) << kClipShift |
                   (munged & kDepthMask) << kMaterialShift |
                   (material & kMaterialMask) << kDepthShift;
        }
    }

    bool transparent() const {
        return (fKey >> kTransparentShift) & kTransparentMask;
    }

    uint32_t clipID() const {
        return (fKey >> kClipShift) & kClipMask;
    }

    uint32_t depth() const {
        if (this->transparent()) {
            return (fKey >> kDepthShift) & kDepthMask;
        }

        // TODO: foo
        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
