1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "GrRenderTarget.h"
10
11#include "GrContext.h"
12#include "GrContextPriv.h"
13#include "GrRenderTargetContext.h"
14#include "GrGpu.h"
15#include "GrRenderTargetOpList.h"
16#include "GrRenderTargetPriv.h"
17#include "GrStencilAttachment.h"
18#include "GrStencilSettings.h"
19#include "SkRectPriv.h"
20
21GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
22                               GrRenderTargetFlags flags,
23                               GrStencilAttachment* stencil)
24        : INHERITED(gpu, desc)
25        , fSampleCnt(desc.fSampleCnt)
26        , fStencilAttachment(stencil)
27        , fMultisampleSpecsID(0)
28        , fFlags(flags) {
29    SkASSERT(desc.fFlags & kRenderTarget_GrSurfaceFlag);
30    SkASSERT(!(fFlags & GrRenderTargetFlags::kMixedSampled) || fSampleCnt > 1);
31    SkASSERT(!(fFlags & GrRenderTargetFlags::kWindowRectsSupport) ||
32             gpu->caps()->maxWindowRectangles() > 0);
33    fResolveRect = SkRectPriv::MakeILargestInverted();
34}
35
36void GrRenderTarget::flagAsNeedingResolve(const SkIRect* rect) {
37    if (kCanResolve_ResolveType == getResolveType()) {
38        if (rect) {
39            fResolveRect.join(*rect);
40            if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
41                fResolveRect.setEmpty();
42            }
43        } else {
44            fResolveRect.setLTRB(0, 0, this->width(), this->height());
45        }
46    }
47}
48
49void GrRenderTarget::overrideResolveRect(const SkIRect rect) {
50    fResolveRect = rect;
51    if (fResolveRect.isEmpty()) {
52        fResolveRect = SkRectPriv::MakeILargestInverted();
53    } else {
54        if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
55            fResolveRect = SkRectPriv::MakeILargestInverted();
56        }
57    }
58}
59
60void GrRenderTarget::flagAsResolved() {
61    fResolveRect = SkRectPriv::MakeILargestInverted();
62}
63
64void GrRenderTarget::onRelease() {
65    SkSafeSetNull(fStencilAttachment);
66
67    INHERITED::onRelease();
68}
69
70void GrRenderTarget::onAbandon() {
71    SkSafeSetNull(fStencilAttachment);
72
73    INHERITED::onAbandon();
74}
75
76///////////////////////////////////////////////////////////////////////////////
77
78bool GrRenderTargetPriv::attachStencilAttachment(sk_sp<GrStencilAttachment> stencil) {
79    if (!stencil && !fRenderTarget->fStencilAttachment) {
80        // No need to do any work since we currently don't have a stencil attachment and
81        // we're not actually adding one.
82        return true;
83    }
84    fRenderTarget->fStencilAttachment = stencil.release();
85    if (!fRenderTarget->completeStencilAttachment()) {
86        SkSafeSetNull(fRenderTarget->fStencilAttachment);
87        return false;
88    }
89    return true;
90}
91
92int GrRenderTargetPriv::numStencilBits() const {
93    SkASSERT(this->getStencilAttachment());
94    return this->getStencilAttachment()->bits();
95}
96
97const GrGpu::MultisampleSpecs&
98GrRenderTargetPriv::getMultisampleSpecs(const GrPipeline& pipeline) const {
99    SkASSERT(fRenderTarget == pipeline.renderTarget()); // TODO: remove RT from pipeline.
100    GrGpu* gpu = fRenderTarget->getGpu();
101    if (auto id = fRenderTarget->fMultisampleSpecsID) {
102        SkASSERT(gpu->queryMultisampleSpecs(pipeline).fUniqueID == id);
103        return gpu->getMultisampleSpecs(id);
104    }
105    const GrGpu::MultisampleSpecs& specs = gpu->queryMultisampleSpecs(pipeline);
106    fRenderTarget->fMultisampleSpecsID = specs.fUniqueID;
107    return specs;
108}
109
110