/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HWUI_BAKED_OP_STATE_H
#define ANDROID_HWUI_BAKED_OP_STATE_H

#include "Matrix.h"
#include "RecordedOp.h"
#include "Rect.h"
#include "Snapshot.h"

namespace android {
namespace uirenderer {

namespace OpClipSideFlags {
    enum {
        None = 0x0,
        Left = 0x1,
        Top = 0x2,
        Right = 0x4,
        Bottom = 0x8,
        Full = 0xF,
        // ConservativeFull = 0x1F  needed?
    };
}

/**
 * Holds a list of BakedOpStates of ops that can be drawn together
 */
struct MergedBakedOpList {
    const BakedOpState*const* states;
    size_t count;
    int clipSideFlags;
    Rect clip;
};

/**
 * Holds the resolved clip, transform, and bounds of a recordedOp, when replayed with a snapshot
 */
class ResolvedRenderState {
public:
    ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
            const RecordedOp& recordedOp, bool expandForStroke);

    // Constructor for unbounded ops *with* transform/clip
    ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
            const Matrix4& localTransform, const ClipBase* localClip);

    // Constructor for unbounded ops without transform/clip (namely shadows)
    ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot);

    // Constructor for primitive ops provided clip, and no transform
    ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect);

    Rect computeLocalSpaceClip() const {
        Matrix4 inverse;
        inverse.loadInverse(transform);

        Rect outClip(clipRect());
        inverse.mapRect(outClip);
        return outClip;
    }

    const Rect& clipRect() const {
        return clipState->rect;
    }

    bool requiresClip() const {
        return clipSideFlags != OpClipSideFlags::None
               || CC_UNLIKELY(clipState->mode != ClipMode::Rectangle);
    }

    // returns the clip if it's needed to draw the operation, otherwise nullptr
    const ClipBase* getClipIfNeeded() const {
        return requiresClip() ? clipState : nullptr;
    }

    Matrix4 transform;
    const ClipBase* clipState = nullptr;
    Rect clippedBounds;
    int clipSideFlags = 0;
    const SkPath* localProjectionPathMask = nullptr;
};

/**
 * Self-contained op wrapper, containing all resolved state required to draw the op.
 *
 * Stashed pointers within all point to longer lived objects, with no ownership implied.
 */
class BakedOpState {
public:
    static BakedOpState* tryConstruct(LinearAllocator& allocator,
            Snapshot& snapshot, const RecordedOp& recordedOp) {
        if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
        BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
                allocator, snapshot, recordedOp, false);
        if (bakedState->computedState.clippedBounds.isEmpty()) {
            // bounds are empty, so op is rejected
            allocator.rewindIfLastAlloc(bakedState);
            return nullptr;
        }
        return bakedState;
    }

    static BakedOpState* tryConstructUnbounded(LinearAllocator& allocator,
            Snapshot& snapshot, const RecordedOp& recordedOp) {
        if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
        return allocator.create_trivial<BakedOpState>(allocator, snapshot, recordedOp);
    }

    enum class StrokeBehavior {
        // stroking is forced, regardless of style on paint (such as for lines)
        Forced,
        // stroking is defined by style on paint
        StyleDefined,
    };

    static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator,
            Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
        if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
        bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
                ? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
                : true;

        BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
                allocator, snapshot, recordedOp, expandForStroke);
        if (bakedState->computedState.clippedBounds.isEmpty()) {
            // bounds are empty, so op is rejected
            // NOTE: this won't succeed if a clip was allocated
            allocator.rewindIfLastAlloc(bakedState);
            return nullptr;
        }
        return bakedState;
    }

    static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator,
            Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
        if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;

        // clip isn't empty, so construct the op
        return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
    }

    static BakedOpState* directConstruct(LinearAllocator& allocator,
            const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
        return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
    }

    // computed state:
    ResolvedRenderState computedState;

    // simple state (straight pointer/value storage):
    const float alpha;
    const RoundRectClipState* roundRectClipState;
    const RecordedOp* op;

private:
    friend class LinearAllocator;

    BakedOpState(LinearAllocator& allocator, Snapshot& snapshot,
            const RecordedOp& recordedOp, bool expandForStroke)
            : computedState(allocator, snapshot, recordedOp, expandForStroke)
            , alpha(snapshot.alpha)
            , roundRectClipState(snapshot.roundRectClipState)
            , op(&recordedOp) {}

    // TODO: fix this brittleness
    BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const RecordedOp& recordedOp)
            : computedState(allocator, snapshot, recordedOp.localMatrix, recordedOp.localClip)
            , alpha(snapshot.alpha)
            , roundRectClipState(snapshot.roundRectClipState)
            , op(&recordedOp) {}

    BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
            : computedState(allocator, snapshot)
            , alpha(snapshot.alpha)
            , roundRectClipState(snapshot.roundRectClipState)
            , op(shadowOpPtr) {}

    BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp)
            : computedState(clipRect, dstRect)
            , alpha(1.0f)
            , roundRectClipState(nullptr)
            , op(&recordedOp) {}
};

}; // namespace uirenderer
}; // namespace android

#endif // ANDROID_HWUI_BAKED_OP_STATE_H
