Add flag for window rectangles to GrRenderTarget

Adds a flag to GrRenderTarget that indicates whether it can be used
with window rectangles. Also attempts to clean up some of the mixed
samples API.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2225303002

Review-Url: https://codereview.chromium.org/2225303002
This commit is contained in:
csmartdalton 2016-08-10 11:09:07 -07:00 committed by Commit bot
parent 4ab47e087e
commit f9635999a4
14 changed files with 180 additions and 146 deletions

View File

@ -263,7 +263,7 @@ public:
return fRenderTarget->isStencilBufferMultisampled(); return fRenderTarget->isStencilBufferMultisampled();
} }
bool isUnifiedMultisampled() const { return fRenderTarget->isUnifiedMultisampled(); } bool isUnifiedMultisampled() const { return fRenderTarget->isUnifiedMultisampled(); }
bool hasMixedSamples() const { return fRenderTarget->hasMixedSamples(); } bool hasMixedSamples() const { return fRenderTarget->isMixedSampled(); }
bool mustUseHWAA(const GrPaint& paint) const { bool mustUseHWAA(const GrPaint& paint) const {
return paint.isAntiAlias() && fRenderTarget->isUnifiedMultisampled(); return paint.isAntiAlias() && fRenderTarget->isUnifiedMultisampled();

View File

@ -30,66 +30,28 @@ public:
const GrRenderTarget* asRenderTarget() const override { return this; } const GrRenderTarget* asRenderTarget() const override { return this; }
// GrRenderTarget // GrRenderTarget
/** bool isStencilBufferMultisampled() const { return fDesc.fSampleCnt > 0; }
* On some hardware it is possible for a render target to have multisampling
* only in certain buffers.
* Enforce only two legal sample configs.
* kUnified_SampleConfig signifies multisampling in both color and stencil
* buffers and is available across all hardware.
* kStencil_SampleConfig means multisampling is present in stencil buffer
* only; this config requires hardware support of
* NV_framebuffer_mixed_samples.
*/
enum SampleConfig {
kUnified_SampleConfig = 0,
kStencil_SampleConfig = 1
};
/** /**
* @return true if the surface is multisampled in all buffers, * For our purposes, "Mixed Sampled" means the stencil buffer is multisampled but the color
* false otherwise * buffer is not.
*/ */
bool isUnifiedMultisampled() const { bool isMixedSampled() const { return fFlags & Flags::kMixedSampled; }
if (fSampleConfig != kUnified_SampleConfig) {
return false;
}
return 0 != fDesc.fSampleCnt;
}
/** /**
* @return true if the surface is multisampled in the stencil buffer, * "Unified Sampled" means the stencil and color buffers are both multisampled.
* false otherwise
*/ */
bool isStencilBufferMultisampled() const { bool isUnifiedMultisampled() const { return fDesc.fSampleCnt > 0 && !this->isMixedSampled(); }
return 0 != fDesc.fSampleCnt;
}
/** /**
* @return the number of color samples-per-pixel, or zero if non-MSAA or * Returns the number of samples/pixel in the stencil buffer (Zero if non-MSAA).
* multisampled in the stencil buffer only.
*/ */
int numColorSamples() const { int numStencilSamples() const { return fDesc.fSampleCnt; }
if (fSampleConfig == kUnified_SampleConfig) {
return fDesc.fSampleCnt;
}
return 0;
}
/** /**
* @return the number of stencil samples-per-pixel, or zero if non-MSAA. * Returns the number of samples/pixel in the color buffer (Zero if non-MSAA or mixed sampled).
*/ */
int numStencilSamples() const { int numColorSamples() const { return this->isMixedSampled() ? 0 : fDesc.fSampleCnt; }
return fDesc.fSampleCnt;
}
/**
* @return true if the surface is mixed sampled, false otherwise.
*/
bool hasMixedSamples() const {
SkASSERT(kStencil_SampleConfig != fSampleConfig ||
this->isStencilBufferMultisampled());
return kStencil_SampleConfig == fSampleConfig;
}
/** /**
* Call to indicate the multisample contents were modified such that the * Call to indicate the multisample contents were modified such that the
@ -156,19 +118,17 @@ public:
void setLastDrawTarget(GrDrawTarget* dt); void setLastDrawTarget(GrDrawTarget* dt);
GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; } GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
static SampleConfig ComputeSampleConfig(const GrCaps& caps, int sampleCnt);
protected: protected:
GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc, enum class Flags {
SampleConfig sampleConfig, GrStencilAttachment* stencil = nullptr) kNone = 0,
: INHERITED(gpu, desc) kMixedSampled = 1 << 0,
, fStencilAttachment(stencil) kWindowRectsSupport = 1 << 1
, fMultisampleSpecsID(0) };
, fSampleConfig(sampleConfig)
, fLastDrawTarget(nullptr) {
fResolveRect.setLargestInverted();
}
GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags);
GrRenderTarget(GrGpu*, const GrSurfaceDesc&, Flags = Flags::kNone,
GrStencilAttachment* = nullptr);
~GrRenderTarget() override; ~GrRenderTarget() override;
// override of GrResource // override of GrResource
@ -186,7 +146,7 @@ private:
GrStencilAttachment* fStencilAttachment; GrStencilAttachment* fStencilAttachment;
uint8_t fMultisampleSpecsID; uint8_t fMultisampleSpecsID;
SampleConfig fSampleConfig; Flags fFlags;
SkIRect fResolveRect; SkIRect fResolveRect;
@ -201,5 +161,6 @@ private:
typedef GrSurface INHERITED; typedef GrSurface INHERITED;
}; };
GR_MAKE_BITFIELD_CLASS_OPS(GrRenderTarget::Flags);
#endif #endif

View File

@ -49,6 +49,27 @@
\ \
template <typename T> \ template <typename T> \
friend X operator & (X a, T b); \ friend X operator & (X a, T b); \
/**
* Defines bitwise operators that make it possible to use an enum class as a
* very basic bitfield.
*/
#define GR_MAKE_BITFIELD_CLASS_OPS(X) \
inline X operator | (X a, X b) { \
return (X) ((int)a | (int)b); \
} \
inline X& operator |= (X& a, X b) { \
return (a = a | b); \
} \
inline bool operator & (X a, X b) { \
return SkToBool((int)a & (int)b); \
}
#define GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(X) \
friend X operator | (X a, X b); \
friend X& operator |= (X& a, X b); \
friend bool operator & (X a, X b);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// compile time versions of min/max // compile time versions of min/max

View File

@ -17,7 +17,7 @@
struct GrInstancedPipelineInfo { struct GrInstancedPipelineInfo {
GrInstancedPipelineInfo(const GrRenderTarget* rt) GrInstancedPipelineInfo(const GrRenderTarget* rt)
: fIsMultisampled(rt->isStencilBufferMultisampled()), : fIsMultisampled(rt->isStencilBufferMultisampled()),
fIsMixedSampled(rt->hasMixedSamples()), fIsMixedSampled(rt->isMixedSampled()),
fIsRenderingToFloat(GrPixelConfigIsFloatingPoint(rt->desc().fConfig)), fIsRenderingToFloat(GrPixelConfigIsFloatingPoint(rt->desc().fConfig)),
fColorDisabled(false), fColorDisabled(false),
fDrawingShapeToStencil(false), fDrawingShapeToStencil(false),

View File

@ -9,6 +9,7 @@
#define GrRenderTargetProxy_DEFINED #define GrRenderTargetProxy_DEFINED
#include "GrRenderTarget.h" #include "GrRenderTarget.h"
#include "GrRenderTargetPriv.h"
#include "GrSurfaceProxy.h" #include "GrSurfaceProxy.h"
#include "GrTypes.h" #include "GrTypes.h"
@ -25,7 +26,7 @@ public:
*/ */
static sk_sp<GrRenderTargetProxy> Make(const GrCaps&, const GrSurfaceDesc&, static sk_sp<GrRenderTargetProxy> Make(const GrCaps&, const GrSurfaceDesc&,
SkBackingFit, SkBudgeted); SkBackingFit, SkBudgeted);
static sk_sp<GrRenderTargetProxy> Make(sk_sp<GrRenderTarget> rt); static sk_sp<GrRenderTargetProxy> Make(const GrCaps&, sk_sp<GrRenderTarget>);
~GrRenderTargetProxy() override; ~GrRenderTargetProxy() override;
@ -36,78 +37,51 @@ public:
// Actually instantiate the backing rendertarget, if necessary. // Actually instantiate the backing rendertarget, if necessary.
GrRenderTarget* instantiate(GrTextureProvider* texProvider); GrRenderTarget* instantiate(GrTextureProvider* texProvider);
/** bool isStencilBufferMultisampled() const { return fDesc.fSampleCnt > 0; }
* @return true if the surface is multisampled in all buffers,
* false otherwise
*/
bool isUnifiedMultisampled() const {
if (fSampleConfig != GrRenderTarget::kUnified_SampleConfig) {
return false;
}
return 0 != fDesc.fSampleCnt;
}
/** /**
* @return true if the surface is multisampled in the stencil buffer, * For our purposes, "Mixed Sampled" means the stencil buffer is multisampled but the color
* false otherwise * buffer is not.
*/ */
bool isStencilBufferMultisampled() const { bool isMixedSampled() const { return fFlags & GrRenderTargetPriv::Flags::kMixedSampled; }
return 0 != fDesc.fSampleCnt;
}
/** /**
* @return the number of color samples-per-pixel, or zero if non-MSAA or * "Unified Sampled" means the stencil and color buffers are both multisampled.
* multisampled in the stencil buffer only.
*/ */
int numColorSamples() const { bool isUnifiedMultisampled() const { return fDesc.fSampleCnt > 0 && !this->isMixedSampled(); }
if (fSampleConfig == GrRenderTarget::kUnified_SampleConfig) {
return fDesc.fSampleCnt;
}
return 0;
}
/** /**
* @return the number of stencil samples-per-pixel, or zero if non-MSAA. * Returns the number of samples/pixel in the stencil buffer (Zero if non-MSAA).
*/ */
int numStencilSamples() const { int numStencilSamples() const { return fDesc.fSampleCnt; }
return fDesc.fSampleCnt;
}
/** /**
* @return true if the surface is mixed sampled, false otherwise. * Returns the number of samples/pixel in the color buffer (Zero if non-MSAA or mixed sampled).
*/ */
bool hasMixedSamples() const { int numColorSamples() const { return this->isMixedSampled() ? 0 : fDesc.fSampleCnt; }
SkASSERT(GrRenderTarget::kStencil_SampleConfig != fSampleConfig ||
this->isStencilBufferMultisampled());
return GrRenderTarget::kStencil_SampleConfig == fSampleConfig;
}
void setLastDrawTarget(GrDrawTarget* dt); void setLastDrawTarget(GrDrawTarget* dt);
GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; } GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
GrRenderTargetPriv::Flags testingOnly_getFlags() const;
private: private:
// TODO: we can probably munge the 'desc' in both the wrapped and deferred // Deferred version
// cases to make the sampleConfig/numSamples stuff more rational. GrRenderTargetProxy(const GrCaps&, const GrSurfaceDesc&, SkBackingFit, SkBudgeted);
GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc& desc,
SkBackingFit fit, SkBudgeted budgeted)
: INHERITED(desc, fit, budgeted)
, fTarget(nullptr)
, fSampleConfig(GrRenderTarget::ComputeSampleConfig(caps, desc.fSampleCnt))
, fLastDrawTarget(nullptr) {
}
// Wrapped version // Wrapped version
GrRenderTargetProxy(sk_sp<GrRenderTarget> rt); GrRenderTargetProxy(const GrCaps&, sk_sp<GrRenderTarget> rt);
// For wrapped render targets we store it here. // For wrapped render targets we store it here.
// For deferred proxies we will fill this in when we need to instantiate the deferred resource // For deferred proxies we will fill this in when we need to instantiate the deferred resource
sk_sp<GrRenderTarget> fTarget; sk_sp<GrRenderTarget> fTarget;
// The sample config doesn't usually get computed until the render target is instantiated but // These don't usually get computed until the render target is instantiated, but the render
// the render target proxy may need to answer queries about it before then. For this reason // target proxy may need to answer queries about it before then. And since in the deferred case
// we precompute it in the deferred case. In the wrapped case we just copy the wrapped // we know the newly created render target will be internal, we are able to precompute what the
// flags will ultimately end up being. In the wrapped case we just copy the wrapped
// rendertarget's info here. // rendertarget's info here.
GrRenderTarget::SampleConfig fSampleConfig; GrRenderTargetPriv::Flags fFlags;
// The last drawTarget that wrote to or is currently going to write to this renderTarget // The last drawTarget that wrote to or is currently going to write to this renderTarget
// The drawTarget can be closed (e.g., no draw context is currently bound // The drawTarget can be closed (e.g., no draw context is currently bound

View File

@ -16,6 +16,18 @@
#include "GrRenderTargetPriv.h" #include "GrRenderTargetPriv.h"
#include "GrStencilAttachment.h" #include "GrStencilAttachment.h"
GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc, Flags flags,
GrStencilAttachment* stencil)
: INHERITED(gpu, desc)
, fStencilAttachment(stencil)
, fMultisampleSpecsID(0)
, fFlags(flags)
, fLastDrawTarget(nullptr) {
SkASSERT(!(fFlags & Flags::kMixedSampled) || fDesc.fSampleCnt > 0);
SkASSERT(!(fFlags & Flags::kWindowRectsSupport) || gpu->caps()->maxWindowRectangles() > 0);
fResolveRect.setLargestInverted();
}
GrRenderTarget::~GrRenderTarget() { GrRenderTarget::~GrRenderTarget() {
if (fLastDrawTarget) { if (fLastDrawTarget) {
fLastDrawTarget->clearRT(); fLastDrawTarget->clearRT();
@ -115,11 +127,3 @@ const GrGpu::MultisampleSpecs&
GrRenderTargetPriv::getMultisampleSpecs(const GrStencilSettings& stencil) const { GrRenderTargetPriv::getMultisampleSpecs(const GrStencilSettings& stencil) const {
return fRenderTarget->getGpu()->getMultisampleSpecs(fRenderTarget, stencil); return fRenderTarget->getGpu()->getMultisampleSpecs(fRenderTarget, stencil);
} }
GrRenderTarget::SampleConfig GrRenderTarget::ComputeSampleConfig(const GrCaps& caps,
int sampleCnt) {
return (caps.usesMixedSamples() && sampleCnt > 0)
? GrRenderTarget::kStencil_SampleConfig
: GrRenderTarget::kUnified_SampleConfig;
}

View File

@ -35,7 +35,10 @@ public:
const GrGpu::MultisampleSpecs& getMultisampleSpecs(const GrStencilSettings& stencil) const; const GrGpu::MultisampleSpecs& getMultisampleSpecs(const GrStencilSettings& stencil) const;
uint8_t& accessMultisampleSpecsID() { return fRenderTarget->fMultisampleSpecsID; } uint8_t& accessMultisampleSpecsID() { return fRenderTarget->fMultisampleSpecsID; }
GrRenderTarget::SampleConfig sampleConfig() const { return fRenderTarget->fSampleConfig; } typedef GrRenderTarget::Flags Flags;
Flags flags() const { return fRenderTarget->fFlags; }
bool supportsWindowRectangles() const { return this->flags() & Flags::kWindowRectsSupport; }
private: private:
explicit GrRenderTargetPriv(GrRenderTarget* renderTarget) : fRenderTarget(renderTarget) {} explicit GrRenderTargetPriv(GrRenderTarget* renderTarget) : fRenderTarget(renderTarget) {}

View File

@ -7,14 +7,34 @@
#include "GrRenderTargetProxy.h" #include "GrRenderTargetProxy.h"
#include "GrCaps.h"
#include "GrDrawTarget.h" #include "GrDrawTarget.h"
#include "GrGpuResourcePriv.h" #include "GrGpuResourcePriv.h"
#include "GrRenderTargetPriv.h"
GrRenderTargetProxy::GrRenderTargetProxy(sk_sp<GrRenderTarget> rt) // Deferred version
// TODO: we can probably munge the 'desc' in both the wrapped and deferred
// cases to make the sampleConfig/numSamples stuff more rational.
GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc& desc,
SkBackingFit fit, SkBudgeted budgeted)
: INHERITED(desc, fit, budgeted)
, fTarget(nullptr)
, fFlags(GrRenderTargetPriv::Flags::kNone)
, fLastDrawTarget(nullptr) {
// Since we know the newly created render target will be internal, we are able to precompute
// what the flags will ultimately end up being.
if (caps.usesMixedSamples() && fDesc.fSampleCnt > 0) {
fFlags |= GrRenderTargetPriv::Flags::kMixedSampled;
}
if (caps.maxWindowRectangles() > 0) {
fFlags |= GrRenderTargetPriv::Flags::kWindowRectsSupport;
}
}
// Wrapped version
GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps, sk_sp<GrRenderTarget> rt)
: INHERITED(rt->desc(), SkBackingFit::kExact, rt->resourcePriv().isBudgeted()) : INHERITED(rt->desc(), SkBackingFit::kExact, rt->resourcePriv().isBudgeted())
, fTarget(std::move(rt)) , fTarget(std::move(rt))
, fSampleConfig(fTarget->renderTargetPriv().sampleConfig()) , fFlags(fTarget->renderTargetPriv().flags())
, fLastDrawTarget(nullptr) { , fLastDrawTarget(nullptr) {
} }
@ -47,7 +67,7 @@ GrRenderTarget* GrRenderTargetProxy::instantiate(GrTextureProvider* texProvider)
fTarget = sk_ref_sp(tex->asRenderTarget()); fTarget = sk_ref_sp(tex->asRenderTarget());
// Check that our a priori computation matched the ultimate reality // Check that our a priori computation matched the ultimate reality
SkASSERT(fSampleConfig == fTarget->renderTargetPriv().sampleConfig()); SkASSERT(fFlags == fTarget->renderTargetPriv().flags());
return fTarget.get(); return fTarget.get();
} }
@ -71,7 +91,7 @@ sk_sp<GrRenderTargetProxy> GrRenderTargetProxy::Make(const GrCaps& caps,
return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(caps, desc, fit, budgeted)); return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(caps, desc, fit, budgeted));
} }
sk_sp<GrRenderTargetProxy> GrRenderTargetProxy::Make(sk_sp<GrRenderTarget> rt) { sk_sp<GrRenderTargetProxy> GrRenderTargetProxy::Make(const GrCaps& caps, sk_sp<GrRenderTarget> rt) {
return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(rt)); return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(caps, rt));
} }

View File

@ -722,7 +722,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
} else { } else {
idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed; idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
} }
idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig; idDesc.fIsMixedSampled = false;
GrSurfaceDesc desc; GrSurfaceDesc desc;
desc.fConfig = wrapDesc.fConfig; desc.fConfig = wrapDesc.fConfig;
@ -1505,7 +1505,7 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
idDesc->fTexFBOID = 0; idDesc->fTexFBOID = 0;
SkASSERT((GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType()) == SkASSERT((GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType()) ==
this->caps()->usesMixedSamples()); this->caps()->usesMixedSamples());
idDesc->fSampleConfig = GrRenderTarget::ComputeSampleConfig(*this->caps(), desc.fSampleCnt); idDesc->fIsMixedSampled = desc.fSampleCnt > 0 && this->caps()->usesMixedSamples();
GrGLenum status; GrGLenum status;
@ -2971,7 +2971,7 @@ void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabl
} }
if (0 != this->caps()->maxRasterSamples()) { if (0 != this->caps()->maxRasterSamples()) {
if (useHWAA && rt->hasMixedSamples() && !stencilEnabled) { if (useHWAA && rt->isMixedSampled() && !stencilEnabled) {
// Since stencil is disabled and we want more samples than are in the color buffer, we // Since stencil is disabled and we want more samples than are in the color buffer, we
// need to tell the rasterizer explicitly how many to run. // need to tell the rasterizer explicitly how many to run.
if (kYes_TriState != fHWRasterMultisampleEnabled) { if (kYes_TriState != fHWRasterMultisampleEnabled) {
@ -2990,7 +2990,7 @@ void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabl
} }
} }
} else { } else {
SkASSERT(!useHWAA || !rt->hasMixedSamples() || stencilEnabled); SkASSERT(!useHWAA || !rt->isMixedSampled() || stencilEnabled);
} }
} }
@ -4440,7 +4440,7 @@ bool GrGLGpu::generateMipmap(GrGLTexture* texture, bool gammaCorrect) {
void GrGLGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings& stencil, void GrGLGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings& stencil,
int* effectiveSampleCnt, SamplePattern* samplePattern) { int* effectiveSampleCnt, SamplePattern* samplePattern) {
SkASSERT(!rt->hasMixedSamples() || rt->renderTargetPriv().getStencilAttachment() || SkASSERT(!rt->isMixedSampled() || rt->renderTargetPriv().getStencilAttachment() ||
stencil.isDisabled()); stencil.isDisabled());
this->flushStencil(stencil); this->flushStencil(stencil);

View File

@ -23,7 +23,7 @@ GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
const IDDesc& idDesc, const IDDesc& idDesc,
GrGLStencilAttachment* stencil) GrGLStencilAttachment* stencil)
: GrSurface(gpu, desc) : GrSurface(gpu, desc)
, INHERITED(gpu, desc, idDesc.fSampleConfig, stencil) { , INHERITED(gpu, desc, ComputeFlags(gpu->glCaps(), idDesc), stencil) {
this->init(desc, idDesc); this->init(desc, idDesc);
this->registerWithCacheWrapped(); this->registerWithCacheWrapped();
} }
@ -31,10 +31,23 @@ GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc,
const IDDesc& idDesc) const IDDesc& idDesc)
: GrSurface(gpu, desc) : GrSurface(gpu, desc)
, INHERITED(gpu, desc, idDesc.fSampleConfig) { , INHERITED(gpu, desc, ComputeFlags(gpu->glCaps(), idDesc)) {
this->init(desc, idDesc); this->init(desc, idDesc);
} }
inline GrRenderTarget::Flags GrGLRenderTarget::ComputeFlags(const GrGLCaps& glCaps,
const IDDesc& idDesc) {
Flags flags = Flags::kNone;
if (idDesc.fIsMixedSampled) {
SkASSERT(glCaps.usesMixedSamples() && idDesc.fRTFBOID); // FBO 0 can't be mixed sampled.
flags |= Flags::kMixedSampled;
}
if (glCaps.maxWindowRectangles() > 0 && idDesc.fRTFBOID) {
flags |= Flags::kWindowRectsSupport;
}
return flags;
}
void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) { void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
fRTFBOID = idDesc.fRTFBOID; fRTFBOID = idDesc.fRTFBOID;
fTexFBOID = idDesc.fTexFBOID; fTexFBOID = idDesc.fTexFBOID;

View File

@ -13,6 +13,7 @@
#include "GrRenderTarget.h" #include "GrRenderTarget.h"
#include "SkScalar.h" #include "SkScalar.h"
class GrGLCaps;
class GrGLGpu; class GrGLGpu;
class GrGLStencilAttachment; class GrGLStencilAttachment;
@ -23,11 +24,11 @@ public:
enum { kUnresolvableFBOID = 0 }; enum { kUnresolvableFBOID = 0 };
struct IDDesc { struct IDDesc {
GrGLuint fRTFBOID; GrGLuint fRTFBOID;
GrBackendObjectOwnership fRTFBOOwnership; GrBackendObjectOwnership fRTFBOOwnership;
GrGLuint fTexFBOID; GrGLuint fTexFBOID;
GrGLuint fMSColorRenderbufferID; GrGLuint fMSColorRenderbufferID;
GrRenderTarget::SampleConfig fSampleConfig; bool fIsMixedSampled;
}; };
static GrGLRenderTarget* CreateWrapped(GrGLGpu*, static GrGLRenderTarget* CreateWrapped(GrGLGpu*,
@ -83,6 +84,8 @@ private:
// Constructor for instances wrapping backend objects. // Constructor for instances wrapping backend objects.
GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrGLStencilAttachment*); GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrGLStencilAttachment*);
static Flags ComputeFlags(const GrGLCaps&, const IDDesc&);
GrGLGpu* getGLGpu() const; GrGLGpu* getGLGpu() const;
bool completeStencilAttachment() override; bool completeStencilAttachment() override;

View File

@ -32,7 +32,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
: GrSurface(gpu, desc) : GrSurface(gpu, desc)
, GrVkImage(info, wrapped) , GrVkImage(info, wrapped)
// for the moment we only support 1:1 color to stencil // for the moment we only support 1:1 color to stencil
, GrRenderTarget(gpu, desc, kUnified_SampleConfig) , GrRenderTarget(gpu, desc)
, fColorAttachmentView(colorAttachmentView) , fColorAttachmentView(colorAttachmentView)
, fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped)) , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped))
, fResolveAttachmentView(resolveAttachmentView) , fResolveAttachmentView(resolveAttachmentView)
@ -57,7 +57,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
: GrSurface(gpu, desc) : GrSurface(gpu, desc)
, GrVkImage(info, wrapped) , GrVkImage(info, wrapped)
// for the moment we only support 1:1 color to stencil // for the moment we only support 1:1 color to stencil
, GrRenderTarget(gpu, desc, kUnified_SampleConfig) , GrRenderTarget(gpu, desc)
, fColorAttachmentView(colorAttachmentView) , fColorAttachmentView(colorAttachmentView)
, fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped)) , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped))
, fResolveAttachmentView(resolveAttachmentView) , fResolveAttachmentView(resolveAttachmentView)
@ -79,7 +79,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
GrVkImage::Wrapped wrapped) GrVkImage::Wrapped wrapped)
: GrSurface(gpu, desc) : GrSurface(gpu, desc)
, GrVkImage(info, wrapped) , GrVkImage(info, wrapped)
, GrRenderTarget(gpu, desc, kUnified_SampleConfig) , GrRenderTarget(gpu, desc)
, fColorAttachmentView(colorAttachmentView) , fColorAttachmentView(colorAttachmentView)
, fMSAAImage(nullptr) , fMSAAImage(nullptr)
, fResolveAttachmentView(nullptr) , fResolveAttachmentView(nullptr)
@ -100,7 +100,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
GrVkImage::Wrapped wrapped) GrVkImage::Wrapped wrapped)
: GrSurface(gpu, desc) : GrSurface(gpu, desc)
, GrVkImage(info, wrapped) , GrVkImage(info, wrapped)
, GrRenderTarget(gpu, desc, kUnified_SampleConfig) , GrRenderTarget(gpu, desc)
, fColorAttachmentView(colorAttachmentView) , fColorAttachmentView(colorAttachmentView)
, fMSAAImage(nullptr) , fMSAAImage(nullptr)
, fResolveAttachmentView(nullptr) , fResolveAttachmentView(nullptr)

View File

@ -10,6 +10,7 @@
#include "Test.h" #include "Test.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrGpu.h"
#include "GrSurfaceProxy.h" #include "GrSurfaceProxy.h"
#include "GrTextureProxy.h" #include "GrTextureProxy.h"
#include "GrRenderTargetProxy.h" #include "GrRenderTargetProxy.h"
@ -50,7 +51,8 @@ static void check_rendertarget(skiatest::Reporter* reporter,
rtProxy->isStencilBufferMultisampled()); rtProxy->isStencilBufferMultisampled());
REPORTER_ASSERT(reporter, rt->numColorSamples() == rtProxy->numColorSamples()); REPORTER_ASSERT(reporter, rt->numColorSamples() == rtProxy->numColorSamples());
REPORTER_ASSERT(reporter, rt->numStencilSamples() == rtProxy->numStencilSamples()); REPORTER_ASSERT(reporter, rt->numStencilSamples() == rtProxy->numStencilSamples());
REPORTER_ASSERT(reporter, rt->hasMixedSamples() == rtProxy->hasMixedSamples()); REPORTER_ASSERT(reporter, rt->isMixedSampled() == rtProxy->isMixedSampled());
REPORTER_ASSERT(reporter, rt->renderTargetPriv().flags() == rtProxy->testingOnly_getFlags());
} }
static void check_texture(skiatest::Reporter* reporter, static void check_texture(skiatest::Reporter* reporter,
@ -124,6 +126,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(AllocedProxyTest, reporter, ctxInfo) {
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) { DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
GrTextureProvider* provider = ctxInfo.grContext()->textureProvider(); GrTextureProvider* provider = ctxInfo.grContext()->textureProvider();
const GrCaps& caps = *ctxInfo.grContext()->caps();
static const int kWidthHeight = 100; static const int kWidthHeight = 100;
@ -131,8 +134,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) { for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) {
for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) { for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) {
for (auto numSamples: { 0, 4}) { for (auto numSamples: { 0, 4}) {
bool renderable = ctxInfo.grContext()->caps()->isConfigRenderable( bool renderable = caps.isConfigRenderable(config, numSamples > 0);
config, numSamples > 0);
GrSurfaceDesc desc; GrSurfaceDesc desc;
desc.fOrigin = origin; desc.fOrigin = origin;
@ -141,14 +143,40 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
desc.fConfig = config; desc.fConfig = config;
desc.fSampleCnt = numSamples; desc.fSampleCnt = numSamples;
// External on-screen render target.
if (renderable && kOpenGL_GrBackend == ctxInfo.backend()) {
GrBackendRenderTargetDesc backendDesc;
backendDesc.fWidth = kWidthHeight;
backendDesc.fHeight = kWidthHeight;
backendDesc.fConfig = config;
backendDesc.fOrigin = origin;
backendDesc.fSampleCnt = numSamples;
backendDesc.fStencilBits = 8;
backendDesc.fRenderTargetHandle = 0;
GrGpu* gpu = ctxInfo.grContext()->getGpu();
sk_sp<GrRenderTarget> defaultFBO(
gpu->wrapBackendRenderTarget(backendDesc, kBorrow_GrWrapOwnership));
SkASSERT(!defaultFBO->renderTargetPriv().supportsWindowRectangles());
sk_sp<GrRenderTargetProxy> rtProxy(
GrRenderTargetProxy::Make(caps, defaultFBO));
check_surface(reporter, rtProxy.get(), origin,
kWidthHeight, kWidthHeight, config);
check_rendertarget(reporter, provider, rtProxy.get(), SkBackingFit::kExact);
}
sk_sp<GrTexture> tex; sk_sp<GrTexture> tex;
// Internal offscreen render target.
if (renderable) { if (renderable) {
desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fFlags = kRenderTarget_GrSurfaceFlag;
tex.reset(provider->createTexture(desc, budgeted)); tex.reset(provider->createTexture(desc, budgeted));
sk_sp<GrRenderTarget> rt(sk_ref_sp(tex->asRenderTarget())); sk_sp<GrRenderTarget> rt(sk_ref_sp(tex->asRenderTarget()));
SkASSERT(caps.maxWindowRectangles() <= 0 ||
rt->renderTargetPriv().supportsWindowRectangles());
sk_sp<GrRenderTargetProxy> rtProxy(GrRenderTargetProxy::Make(rt)); sk_sp<GrRenderTargetProxy> rtProxy(GrRenderTargetProxy::Make(caps, rt));
check_surface(reporter, rtProxy.get(), origin, check_surface(reporter, rtProxy.get(), origin,
kWidthHeight, kWidthHeight, config); kWidthHeight, kWidthHeight, config);
check_rendertarget(reporter, provider, rtProxy.get(), SkBackingFit::kExact); check_rendertarget(reporter, provider, rtProxy.get(), SkBackingFit::kExact);

View File

@ -13,6 +13,7 @@
#include "GrDrawingManager.h" #include "GrDrawingManager.h"
#include "GrGpuResourceCacheAccess.h" #include "GrGpuResourceCacheAccess.h"
#include "GrPipelineBuilder.h" #include "GrPipelineBuilder.h"
#include "GrRenderTargetProxy.h"
#include "GrResourceCache.h" #include "GrResourceCache.h"
#include "SkGpuDevice.h" #include "SkGpuDevice.h"
@ -257,6 +258,12 @@ void GrDrawContextPriv::testingOnly_drawBatch(const GrPaint& paint,
#undef ASSERT_SINGLE_OWNER #undef ASSERT_SINGLE_OWNER
#undef RETURN_IF_ABANDONED #undef RETURN_IF_ABANDONED
///////////////////////////////////////////////////////////////////////////////
GrRenderTargetPriv::Flags GrRenderTargetProxy::testingOnly_getFlags() const {
return fFlags;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Code for the mock context. It's built on a mock GrGpu class that does nothing. // Code for the mock context. It's built on a mock GrGpu class that does nothing.
//// ////