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

#ifndef GrMtlDepthStencil_DEFINED
#define GrMtlDepthStencil_DEFINED

#import <Metal/Metal.h>

#include "include/gpu/GrTypes.h"
#include "src/core/SkOpts.h"
#include "src/gpu/GrManagedResource.h"
#include <atomic>

class GrMtlGpu;
class GrStencilSettings;

// A wrapper for a MTLDepthStencilState object with caching support.
class GrMtlDepthStencil : public GrManagedResource {
public:
    static GrMtlDepthStencil* Create(const GrMtlGpu*, const GrStencilSettings&, GrSurfaceOrigin);

    ~GrMtlDepthStencil() override { fMtlDepthStencilState = nil; }

    id<MTLDepthStencilState> mtlDepthStencil() const { return fMtlDepthStencilState; }

    struct Key {
        struct Face {
            uint32_t fReadMask;
            uint32_t fWriteMask;
            uint32_t fOps;
        };
        Face fFront;
        Face fBack;

        bool operator==(const Key& that) const {
            return this->fFront.fReadMask == that.fFront.fReadMask &&
                   this->fFront.fWriteMask == that.fFront.fWriteMask &&
                   this->fFront.fOps == that.fFront.fOps &&
                   this->fBack.fReadMask == that.fBack.fReadMask &&
                   this->fBack.fWriteMask == that.fBack.fWriteMask &&
                   this->fBack.fOps == that.fBack.fOps;
        }
    };

    // Helpers for hashing GrMtlDepthStencil
    static Key GenerateKey(const GrStencilSettings&, GrSurfaceOrigin);

    static const Key& GetKey(const GrMtlDepthStencil& depthStencil) { return depthStencil.fKey; }
    static uint32_t Hash(const Key& key) {
        return SkOpts::hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
    }

#ifdef SK_TRACE_MANAGED_RESOURCES
    /** output a human-readable dump of this resource's information
     */
    void dumpInfo() const override {
        SkDebugf("GrMtlDepthStencil: %p (%ld refs)\n", fMtlDepthStencilState,
                 CFGetRetainCount((CFTypeRef)fMtlDepthStencilState));
    }
#endif

    void freeGPUData() const override {
        fMtlDepthStencilState = nil;
    }

private:
    GrMtlDepthStencil(id<MTLDepthStencilState> mtlDepthStencilState, Key key)
        : fMtlDepthStencilState(mtlDepthStencilState)
        , fKey(key) {}

    mutable id<MTLDepthStencilState> fMtlDepthStencilState;
    Key                      fKey;
};

#endif
