/*
 * 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 "include/gpu/GrRenderTarget.h"

#include "include/gpu/GrContext.h"
#include "src/core/SkRectPriv.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrRenderTargetOpList.h"
#include "src/gpu/GrRenderTargetPriv.h"
#include "src/gpu/GrSamplePatternDictionary.h"
#include "src/gpu/GrStencilAttachment.h"
#include "src/gpu/GrStencilSettings.h"

GrRenderTarget::GrRenderTarget(GrGpu* gpu, const SkISize& size, GrPixelConfig config,
                               int sampleCount, GrProtected isProtected,
                               GrStencilAttachment* stencil)
        : INHERITED(gpu, size, config, isProtected)
        , fSampleCnt(sampleCount)
        , fSamplePatternKey(GrSamplePatternDictionary::kInvalidSamplePatternKey)
        , fStencilAttachment(stencil) {
    fResolveRect = SkRectPriv::MakeILargestInverted();
}

GrRenderTarget::~GrRenderTarget() = default;

void GrRenderTarget::flagAsNeedingResolve(const SkIRect* rect) {
    if (kCanResolve_ResolveType == getResolveType()) {
        if (rect) {
            fResolveRect.join(*rect);
            if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
                fResolveRect.setEmpty();
            }
        } else {
            fResolveRect.setLTRB(0, 0, this->width(), this->height());
        }
    }
}

void GrRenderTarget::flagAsResolved() {
    fResolveRect = SkRectPriv::MakeILargestInverted();
}

void GrRenderTarget::onRelease() {
    fStencilAttachment = nullptr;

    INHERITED::onRelease();
}

void GrRenderTarget::onAbandon() {
    fStencilAttachment = nullptr;

    INHERITED::onAbandon();
}

///////////////////////////////////////////////////////////////////////////////

void GrRenderTargetPriv::attachStencilAttachment(sk_sp<GrStencilAttachment> stencil) {
#ifdef SK_DEBUG
    if (1 == fRenderTarget->fSampleCnt) {
        // TODO: We don't expect a mixed sampled render target to ever change its stencil buffer
        // right now. But if it does swap in a stencil buffer with a different number of samples,
        // and if we have a valid fSamplePatternKey, we will need to invalidate fSamplePatternKey
        // here and add tests to make sure we it properly.
        SkASSERT(GrSamplePatternDictionary::kInvalidSamplePatternKey ==
                 fRenderTarget->fSamplePatternKey);
    } else {
        // Render targets with >1 color sample should never use mixed samples. (This would lead to
        // different sample patterns, depending on stencil state.)
        SkASSERT(!stencil || stencil->numSamples() == fRenderTarget->fSampleCnt);
    }
#endif

    if (!stencil && !fRenderTarget->fStencilAttachment) {
        // No need to do any work since we currently don't have a stencil attachment and
        // we're not actually adding one.
        return;
    }

    fRenderTarget->fStencilAttachment = std::move(stencil);
    if (!fRenderTarget->completeStencilAttachment()) {
        fRenderTarget->fStencilAttachment = nullptr;
    }
}

int GrRenderTargetPriv::numStencilBits() const {
    SkASSERT(this->getStencilAttachment());
    return this->getStencilAttachment()->bits();
}

int GrRenderTargetPriv::getSamplePatternKey() const {
#ifdef SK_DEBUG
    GrStencilAttachment* stencil = fRenderTarget->fStencilAttachment.get();
    if (fRenderTarget->fSampleCnt <= 1) {
        // If the color buffer is not multisampled, the sample pattern better come from the stencil
        // buffer (mixed samples).
        SkASSERT(stencil && stencil->numSamples() > 1);
    } else {
        // The color sample count and stencil count cannot both be unequal and both greater than
        // one. If this were the case, there would be more than one sample pattern associated with
        // the render target.
        SkASSERT(!stencil || stencil->numSamples() == fRenderTarget->fSampleCnt);
    }
#endif
    if (GrSamplePatternDictionary::kInvalidSamplePatternKey == fRenderTarget->fSamplePatternKey) {
        fRenderTarget->fSamplePatternKey =
                fRenderTarget->getGpu()->findOrAssignSamplePatternKey(fRenderTarget);
    }
    SkASSERT(GrSamplePatternDictionary::kInvalidSamplePatternKey
                     != fRenderTarget->fSamplePatternKey);
    return fRenderTarget->fSamplePatternKey;
}
