/*
 * 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/GrStencilSettings.h"

#include "src/gpu/GrProcessor.h"
#include "src/gpu/KeyBuilder.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));
}
