/*
 * 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/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/GrRenderTargetPriv.h"
#include "src/gpu/GrSamplePatternDictionary.h"
#include "src/gpu/GrStencilAttachment.h"
#include "src/gpu/GrStencilSettings.h"

GrRenderTarget::GrRenderTarget(GrGpu* gpu, const SkISize& dimensions, int sampleCount,
                               GrProtected isProtected, GrStencilAttachment* stencil)
        : INHERITED(gpu, dimensions, isProtected)
        , fSampleCnt(sampleCount)
        , fSamplePatternKey(GrSamplePatternDictionary::kInvalidSamplePatternKey)
        , fStencilAttachment(stencil) {}

GrRenderTarget::~GrRenderTarget() = default;

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;
}
