/*
 * 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 GrDstProxyView_DEFINED
#define GrDstProxyView_DEFINED

#include "include/core/SkPoint.h"
#include "include/private/base/SkTypeTraits.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"

#include <type_traits>
#include <utility>

class GrSurfaceProxy;

/**
 * GrDstProxyView holds a texture containing the destination pixel values, and an integer-coordinate
 * offset from device-space to the space of the texture. When framebuffer fetch is not available, a
 * GrDstProxyView may be used to support blending in the fragment shader/xfer processor.
 */
class GrDstProxyView {
public:
    GrDstProxyView() {}

    GrDstProxyView(const GrDstProxyView& other) {
        *this = other;
    }

    GrDstProxyView& operator=(const GrDstProxyView& other) {
        fProxyView = other.fProxyView;
        fOffset = other.fOffset;
        fDstSampleFlags = other.fDstSampleFlags;
        return *this;
    }

    bool operator==(const GrDstProxyView& that) const {
        return fProxyView == that.fProxyView &&
               fOffset == that.fOffset &&
               fDstSampleFlags == that.fDstSampleFlags;
    }
    bool operator!=(const GrDstProxyView& that) const { return !(*this == that); }

    const SkIPoint& offset() const { return fOffset; }

    void setOffset(const SkIPoint& offset) { fOffset = offset; }
    void setOffset(int ox, int oy) { fOffset.set(ox, oy); }

    GrSurfaceProxy* proxy() const { return fProxyView.proxy(); }
    const GrSurfaceProxyView& proxyView() const { return fProxyView; }

    void setProxyView(GrSurfaceProxyView view) {
        fProxyView = std::move(view);
        if (!fProxyView.proxy()) {
            fOffset = {0, 0};
        }
    }

    GrDstSampleFlags dstSampleFlags() const { return fDstSampleFlags; }

    void setDstSampleFlags(GrDstSampleFlags dstSampleFlags) { fDstSampleFlags = dstSampleFlags; }

    using sk_is_trivially_relocatable = std::true_type;

private:
    GrSurfaceProxyView       fProxyView;
    SkIPoint                 fOffset = {0, 0};
    GrDstSampleFlags         fDstSampleFlags = GrDstSampleFlags::kNone;

    static_assert(::sk_is_trivially_relocatable<decltype(fProxyView)>::value);
    static_assert(::sk_is_trivially_relocatable<decltype(fOffset)>::value);
    static_assert(::sk_is_trivially_relocatable<decltype(fDstSampleFlags)>::value);
};

#endif
