/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "src/gpu/ganesh/GrStencilSettings.h"

#include "src/gpu/KeyBuilder.h"
#include "src/gpu/ganesh/GrProcessor.h"

constexpr const GrUserStencilSettings gUnused(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlwaysIfInClip,
        0xffff,
        GrUserStencilOp::kKeep,
        GrUserStencilOp::kKeep,
        0x0000>()
);

static_assert(kAll_StencilFlags == (gUnused.fCWFlags[0] & gUnused.fCCWFlags[0]));

const GrUserStencilSettings& GrUserStencilSettings::kUnused = gUnused;

void GrStencilSettings::reset(const GrUserStencilSettings& user, bool hasStencilClip,
                              int numStencilBits) {
    uint16_t cwFlags = user.fCWFlags[hasStencilClip];
    if (cwFlags & kSingleSided_StencilFlag) {
        SkASSERT(cwFlags == user.fCCWFlags[hasStencilClip]);
        fFlags = cwFlags;
        if (!this->isDisabled()) {
            fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
        }
        return;
    }

    uint16_t ccwFlags = user.fCCWFlags[hasStencilClip];
    fFlags = cwFlags & ccwFlags;
    if (this->isDisabled()) {
        return;
    }
    if (!(cwFlags & kDisabled_StencilFlag)) {
        fCWFace.reset(user.fCWFace, hasStencilClip, numStencilBits);
    } else {
        fCWFace.setDisabled();
    }
    if (!(ccwFlags & kDisabled_StencilFlag)) {
        fCCWFace.reset(user.fCCWFace, hasStencilClip, numStencilBits);
    } else {
        fCCWFace.setDisabled();
    }
}

void GrStencilSettings::reset(const GrStencilSettings& that) {
    fFlags = that.fFlags;
    if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & fFlags) {
        return;
    }
    if (!this->isTwoSided()) {
        memcpy(&fCWFace, &that.fCWFace, sizeof(Face));
    } else {
        memcpy(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
        static_assert(sizeof(Face) ==
                      offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
    }
}

bool GrStencilSettings::operator==(const GrStencilSettings& that) const {
    if ((kInvalid_PrivateFlag | kDisabled_StencilFlag) & (fFlags | that.fFlags)) {
        // At least one is invalid and/or disabled.
        if (kInvalid_PrivateFlag & (fFlags | that.fFlags)) {
            return false; // We never allow invalid stencils to be equal.
        }
        // They're only equal if both are disabled.
        return kDisabled_StencilFlag & (fFlags & that.fFlags);
    }
    if (kSingleSided_StencilFlag & (fFlags & that.fFlags)) {
        return 0 == memcmp(&fCWFace, &that.fCWFace, sizeof(Face)); // Both are single sided.
    } else if (kSingleSided_StencilFlag & (fFlags | that.fFlags)) {
        return false;
    } else {
        return 0 == memcmp(&fCWFace, &that.fCWFace, 2 * sizeof(Face));
        static_assert(sizeof(Face) ==
                      offsetof(GrStencilSettings, fCCWFace) - offsetof(GrStencilSettings, fCWFace));
    }
    // memcmp relies on GrStencilSettings::Face being tightly packed.
    static_assert(0 == offsetof(Face, fRef));
    static_assert(2 == sizeof(Face::fRef));
    static_assert(2 == offsetof(Face, fTest));
    static_assert(2 == sizeof(Face::fTest));
    static_assert(4 == offsetof(Face, fTestMask));
    static_assert(2 == sizeof(Face::fTestMask));
    static_assert(6 == offsetof(Face, fPassOp));
    static_assert(1 == sizeof(Face::fPassOp));
    static_assert(7 == offsetof(Face, fFailOp));
    static_assert(1 == sizeof(Face::fFailOp));
    static_assert(8 == offsetof(Face, fWriteMask));
    static_assert(2 == sizeof(Face::fWriteMask));
    static_assert(10 == sizeof(Face));
}

static constexpr GrStencilTest gUserStencilTestToRaw[kGrUserStencilTestCount] = {
    // Tests that respect the clip.
    GrStencilTest::kAlways,  // kAlwaysIfInClip (This is only for when there is not a stencil clip).
    GrStencilTest::kEqual,   // kEqualIfInClip.
    GrStencilTest::kLess,    // kLessIfInClip.
    GrStencilTest::kLEqual,  // kLEqualIfInClip.

    // Tests that ignore the clip.
    GrStencilTest::kAlways,
    GrStencilTest::kNever,
    GrStencilTest::kGreater,
    GrStencilTest::kGEqual,
    GrStencilTest::kLess,
    GrStencilTest::kLEqual,
    GrStencilTest::kEqual,
    GrStencilTest::kNotEqual
};

static_assert(0 == (int)GrUserStencilTest::kAlwaysIfInClip);
static_assert(1 == (int)GrUserStencilTest::kEqualIfInClip);
static_assert(2 == (int)GrUserStencilTest::kLessIfInClip);
static_assert(3 == (int)GrUserStencilTest::kLEqualIfInClip);
static_assert(4 == (int)GrUserStencilTest::kAlways);
static_assert(5 == (int)GrUserStencilTest::kNever);
static_assert(6 == (int)GrUserStencilTest::kGreater);
static_assert(7 == (int)GrUserStencilTest::kGEqual);
static_assert(8 == (int)GrUserStencilTest::kLess);
static_assert(9 == (int)GrUserStencilTest::kLEqual);
static_assert(10 == (int)GrUserStencilTest::kEqual);
static_assert(11 == (int)GrUserStencilTest::kNotEqual);

static constexpr GrStencilOp gUserStencilOpToRaw[kGrUserStencilOpCount] = {
    GrStencilOp::kKeep,

    // Ops that only modify user bits.
    GrStencilOp::kZero,
    GrStencilOp::kReplace,
    GrStencilOp::kInvert,
    GrStencilOp::kIncWrap,
    GrStencilOp::kDecWrap,
    GrStencilOp::kIncClamp,  // kIncMaybeClamp.
    GrStencilOp::kDecClamp,  // kDecMaybeClamp.

    // Ops that only modify the clip bit.
    GrStencilOp::kZero,      // kZeroClipBit.
    GrStencilOp::kReplace,   // kSetClipBit.
    GrStencilOp::kInvert,    // kInvertClipBit.

    // Ops that modify clip and user bits.
    GrStencilOp::kReplace,   // kSetClipAndReplaceUserBits.
    GrStencilOp::kZero       // kZeroClipAndUserBits.
};

static_assert(0 == (int)GrUserStencilOp::kKeep);
static_assert(1 == (int)GrUserStencilOp::kZero);
static_assert(2 == (int)GrUserStencilOp::kReplace);
static_assert(3 == (int)GrUserStencilOp::kInvert);
static_assert(4 == (int)GrUserStencilOp::kIncWrap);
static_assert(5 == (int)GrUserStencilOp::kDecWrap);
static_assert(6 == (int)GrUserStencilOp::kIncMaybeClamp);
static_assert(7 == (int)GrUserStencilOp::kDecMaybeClamp);
static_assert(8 == (int)GrUserStencilOp::kZeroClipBit);
static_assert(9 == (int)GrUserStencilOp::kSetClipBit);
static_assert(10 == (int)GrUserStencilOp::kInvertClipBit);
static_assert(11 == (int)GrUserStencilOp::kSetClipAndReplaceUserBits);
static_assert(12 == (int)GrUserStencilOp::kZeroClipAndUserBits);

void GrStencilSettings::Face::reset(const GrUserStencilSettings::Face& user, bool hasStencilClip,
                                    int numStencilBits) {
    SkASSERT(user.fTest < (GrUserStencilTest)kGrUserStencilTestCount);
    SkASSERT(user.fPassOp < (GrUserStencilOp)kGrUserStencilOpCount);
    SkASSERT(user.fFailOp < (GrUserStencilOp)kGrUserStencilOpCount);
    SkASSERT(numStencilBits > 0 && numStencilBits <= 16);
    int clipBit = 1 << (numStencilBits - 1);
    int userMask = clipBit - 1;

    GrUserStencilOp maxOp = std::max(user.fPassOp, user.fFailOp);
    SkDEBUGCODE(GrUserStencilOp otherOp = std::min(user.fPassOp, user.fFailOp);)
    if (maxOp <= kLastUserOnlyStencilOp) {
        // Ops that only modify user bits.
        fWriteMask = user.fWriteMask & userMask;
        SkASSERT(otherOp <= kLastUserOnlyStencilOp);
    } else if (maxOp <= kLastClipOnlyStencilOp) {
        // Ops that only modify the clip bit.
        fWriteMask = clipBit;
        SkASSERT(GrUserStencilOp::kKeep == otherOp ||
                 (otherOp > kLastUserOnlyStencilOp && otherOp <= kLastClipOnlyStencilOp));
    } else {
        // Ops that modify both clip and user bits.
        fWriteMask = clipBit | (user.fWriteMask & userMask);
        SkASSERT(GrUserStencilOp::kKeep == otherOp || otherOp > kLastClipOnlyStencilOp);
    }

    fFailOp = gUserStencilOpToRaw[(int)user.fFailOp];
    fPassOp = gUserStencilOpToRaw[(int)user.fPassOp];

    if (!hasStencilClip || user.fTest > kLastClippedStencilTest) {
        // Ignore the clip.
        fTestMask = user.fTestMask & userMask;
        fTest = gUserStencilTestToRaw[(int)user.fTest];
    } else if (GrUserStencilTest::kAlwaysIfInClip != user.fTest) {
        // Respect the clip.
        fTestMask = clipBit | (user.fTestMask & userMask);
        fTest = gUserStencilTestToRaw[(int)user.fTest];
    } else {
        // Test only for clip.
        fTestMask = clipBit;
        fTest = GrStencilTest::kEqual;
    }

    fRef = (clipBit | user.fRef) & (fTestMask | fWriteMask);
}

void GrStencilSettings::Face::setDisabled() {
    memset(this, 0, sizeof(*this));
    static_assert(0 == (int)GrStencilTest::kAlways);
    static_assert(0 == (int)GrStencilOp::kKeep);
}

static constexpr GrUserStencilSettings gZeroStencilClipBit(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlways,
        0xffff,
        GrUserStencilOp::kZeroClipBit,
        GrUserStencilOp::kZeroClipBit,
        0x0000>()
);
static constexpr GrUserStencilSettings gSetStencilClipBit(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlways,
        0xffff,
        GrUserStencilOp::kSetClipBit,
        GrUserStencilOp::kSetClipBit,
        0x0000>()
);

const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
    return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit;
}

void GrStencilSettings::genKey(skgpu::KeyBuilder* b, bool includeRefs) const {
    b->addBits(6, fFlags, "stencilFlags");
    if (this->isDisabled()) {
        return;
    }
    if (!this->isTwoSided()) {
        if (includeRefs) {
            b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
        } else {
            Face tempFace = fCWFace;
            tempFace.fRef = 0;
            b->addBytes(sizeof(Face), &tempFace, "stencilCWFace");
        }
    } else {
        if (includeRefs) {
            b->addBytes(sizeof(Face), &fCWFace, "stencilCWFace");
            b->addBytes(sizeof(Face), &fCCWFace, "stencilCCWFace");
        } else {
            Face tempFaces[2];
            tempFaces[0] = fCWFace;
            tempFaces[0].fRef = 0;
            tempFaces[1] = fCCWFace;
            tempFaces[1].fRef = 0;
            b->addBytes(sizeof(Face), &tempFaces[0], "stencilCWFace");
            b->addBytes(sizeof(Face), &tempFaces[1], "stencilCCWFace");
        }
    }
    // We rely on GrStencilSettings::Face being tightly packed for the key to be reliable.
    static_assert(0 == offsetof(Face, fRef));
    static_assert(2 == sizeof(Face::fRef));
    static_assert(2 == offsetof(Face, fTest));
    static_assert(2 == sizeof(Face::fTest));
    static_assert(4 == offsetof(Face, fTestMask));
    static_assert(2 == sizeof(Face::fTestMask));
    static_assert(6 == offsetof(Face, fPassOp));
    static_assert(1 == sizeof(Face::fPassOp));
    static_assert(7 == offsetof(Face, fFailOp));
    static_assert(1 == sizeof(Face::fFailOp));
    static_assert(8 == offsetof(Face, fWriteMask));
    static_assert(2 == sizeof(Face::fWriteMask));
    static_assert(10 == sizeof(Face));
}
