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 "GrDrawContext.h"
14 #include "GrDrawTarget.h"
15 #include "GrGpu.h"
16 #include "GrRenderTargetPriv.h"
17 #include "GrStencilAttachment.h"
18 
GrRenderTarget(GrGpu * gpu,const GrSurfaceDesc & desc,Flags flags,GrStencilAttachment * stencil)19 GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc, Flags flags,
20                                GrStencilAttachment* stencil)
21     : INHERITED(gpu, desc)
22     , fStencilAttachment(stencil)
23     , fMultisampleSpecsID(0)
24     , fFlags(flags)
25     , fLastDrawTarget(nullptr) {
26     SkASSERT(!(fFlags & Flags::kMixedSampled) || fDesc.fSampleCnt > 0);
27     SkASSERT(!(fFlags & Flags::kWindowRectsSupport) || gpu->caps()->maxWindowRectangles() > 0);
28     fResolveRect.setLargestInverted();
29 }
30 
~GrRenderTarget()31 GrRenderTarget::~GrRenderTarget() {
32     if (fLastDrawTarget) {
33         fLastDrawTarget->clearRT();
34     }
35     SkSafeUnref(fLastDrawTarget);
36 }
37 
discard()38 void GrRenderTarget::discard() {
39     // go through context so that all necessary flushing occurs
40     GrContext* context = this->getContext();
41     if (!context) {
42         return;
43     }
44 
45     sk_sp<GrDrawContext> drawContext(context->contextPriv().makeWrappedDrawContext(sk_ref_sp(this),
46                                                                                    nullptr));
47     if (!drawContext) {
48         return;
49     }
50 
51     drawContext->discard();
52 }
53 
flagAsNeedingResolve(const SkIRect * rect)54 void GrRenderTarget::flagAsNeedingResolve(const SkIRect* rect) {
55     if (kCanResolve_ResolveType == getResolveType()) {
56         if (rect) {
57             fResolveRect.join(*rect);
58             if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
59                 fResolveRect.setEmpty();
60             }
61         } else {
62             fResolveRect.setLTRB(0, 0, this->width(), this->height());
63         }
64     }
65 }
66 
overrideResolveRect(const SkIRect rect)67 void GrRenderTarget::overrideResolveRect(const SkIRect rect) {
68     fResolveRect = rect;
69     if (fResolveRect.isEmpty()) {
70         fResolveRect.setLargestInverted();
71     } else {
72         if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
73             fResolveRect.setLargestInverted();
74         }
75     }
76 }
77 
onRelease()78 void GrRenderTarget::onRelease() {
79     SkSafeSetNull(fStencilAttachment);
80 
81     INHERITED::onRelease();
82 }
83 
onAbandon()84 void GrRenderTarget::onAbandon() {
85     SkSafeSetNull(fStencilAttachment);
86 
87     // The contents of this renderTarget are gone/invalid. It isn't useful to point back
88     // the creating drawTarget.
89     this->setLastDrawTarget(nullptr);
90 
91     INHERITED::onAbandon();
92 }
93 
setLastDrawTarget(GrDrawTarget * dt)94 void GrRenderTarget::setLastDrawTarget(GrDrawTarget* dt) {
95     if (fLastDrawTarget) {
96         // The non-MDB world never closes so we can't check this condition
97 #ifdef ENABLE_MDB
98         SkASSERT(fLastDrawTarget->isClosed());
99 #endif
100         fLastDrawTarget->clearRT();
101     }
102 
103     SkRefCnt_SafeAssign(fLastDrawTarget, dt);
104 }
105 
106 ///////////////////////////////////////////////////////////////////////////////
107 
attachStencilAttachment(GrStencilAttachment * stencil)108 bool GrRenderTargetPriv::attachStencilAttachment(GrStencilAttachment* stencil) {
109     if (!stencil && !fRenderTarget->fStencilAttachment) {
110         // No need to do any work since we currently don't have a stencil attachment and
111         // we're not acctually adding one.
112         return true;
113     }
114     fRenderTarget->fStencilAttachment = stencil;
115     if (!fRenderTarget->completeStencilAttachment()) {
116         SkSafeSetNull(fRenderTarget->fStencilAttachment);
117         return false;
118     }
119     return true;
120 }
121 
numStencilBits() const122 int GrRenderTargetPriv::numStencilBits() const {
123     return fRenderTarget->fStencilAttachment ? fRenderTarget->fStencilAttachment->bits() : 0;
124 }
125 
126 const GrGpu::MultisampleSpecs&
getMultisampleSpecs(const GrStencilSettings & stencil) const127 GrRenderTargetPriv::getMultisampleSpecs(const GrStencilSettings& stencil) const {
128     return fRenderTarget->getGpu()->getMultisampleSpecs(fRenderTarget, stencil);
129 }
130 
maxWindowRectangles() const131 int GrRenderTargetPriv::maxWindowRectangles() const {
132     return (this->flags() & Flags::kWindowRectsSupport) ?
133            fRenderTarget->getGpu()->caps()->maxWindowRectangles() : 0;
134 }
135