Revert "Drop support for unused MSAA extensions"

This reverts commit 7df27465c4.

Reason for revert: experimental revert to see if this is the cause of the tree redness

Original change's description:
> Drop support for unused MSAA extensions
> 
> Bug: skia:
> Change-Id: I113b80e3f991f195155148625ceb29242ea82776
> Reviewed-on: https://skia-review.googlesource.com/101403
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Chris Dalton <csmartdalton@google.com>

TBR=bsalomon@google.com,csmartdalton@google.com,ethannicholas@google.com

Change-Id: I4fa4123e2d176bef88cd76a09a14053d9ac5809f
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/101680
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2018-01-30 13:13:42 +00:00 committed by Skia Commit-Bot
parent 2f5b8d81c2
commit 7f861927fc
58 changed files with 759 additions and 65 deletions

View File

@ -89,6 +89,7 @@ tests_sources = [
"$_tests/GpuDrawPathTest.cpp",
"$_tests/GpuLayerCacheTest.cpp",
"$_tests/GpuRectanizerTest.cpp",
"$_tests/GpuSampleLocationsTest.cpp",
"$_tests/GradientTest.cpp",
"$_tests/GrAllocatorTest.cpp",
"$_tests/GrCCPRTest.cpp",

View File

@ -52,6 +52,7 @@ public:
bool gpuTracingSupport() const { return fGpuTracingSupport; }
bool oversizedStencilSupport() const { return fOversizedStencilSupport; }
bool textureBarrierSupport() const { return fTextureBarrierSupport; }
bool sampleLocationsSupport() const { return fSampleLocationsSupport; }
bool multisampleDisableSupport() const { return fMultisampleDisableSupport; }
bool instanceAttribSupport() const { return fInstanceAttribSupport; }
bool usesMixedSamples() const { return fUsesMixedSamples; }
@ -206,6 +207,7 @@ protected:
bool fGpuTracingSupport : 1;
bool fOversizedStencilSupport : 1;
bool fTextureBarrierSupport : 1;
bool fSampleLocationsSupport : 1;
bool fMultisampleDisableSupport : 1;
bool fInstanceAttribSupport : 1;
bool fUsesMixedSamples : 1;

View File

@ -134,6 +134,7 @@ private:
int fSampleCnt;
GrStencilAttachment* fStencilAttachment;
uint8_t fMultisampleSpecsID;
GrRenderTargetFlags fFlags;
SkIRect fResolveRect;

View File

@ -72,6 +72,12 @@ public:
bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
bool multisampleInterpolationSupport() const { return fMultisampleInterpolationSupport; }
bool sampleVariablesSupport() const { return fSampleVariablesSupport; }
bool sampleMaskOverrideCoverageSupport() const { return fSampleMaskOverrideCoverageSupport; }
bool externalTextureSupport() const { return fExternalTextureSupport; }
bool texelFetchSupport() const { return fTexelFetchSupport; }
@ -186,6 +192,16 @@ public:
return fNoPerspectiveInterpolationExtensionString;
}
const char* multisampleInterpolationExtensionString() const {
SkASSERT(this->multisampleInterpolationSupport());
return fMultisampleInterpolationExtensionString;
}
const char* sampleVariablesExtensionString() const {
SkASSERT(this->sampleVariablesSupport());
return fSampleVariablesExtensionString;
}
const char* imageLoadStoreExtensionString() const {
SkASSERT(this->imageLoadStoreSupport());
return fImageLoadStoreExtensionString;
@ -246,6 +262,9 @@ private:
bool fFlatInterpolationSupport : 1;
bool fPreferFlatInterpolation : 1;
bool fNoPerspectiveInterpolationSupport : 1;
bool fMultisampleInterpolationSupport : 1;
bool fSampleVariablesSupport : 1;
bool fSampleMaskOverrideCoverageSupport : 1;
bool fExternalTextureSupport : 1;
bool fTexelFetchSupport : 1;
bool fVertexIDSupport : 1;
@ -275,6 +294,8 @@ private:
const char* fExternalTextureExtensionString;
const char* fTexelBufferExtensionString;
const char* fNoPerspectiveInterpolationExtensionString;
const char* fMultisampleInterpolationExtensionString;
const char* fSampleVariablesExtensionString;
const char* fImageLoadStoreExtensionString;
const char* fFBFetchColorName;

View File

@ -50,6 +50,7 @@ GrCaps::GrCaps(const GrContextOptions& options) {
fGpuTracingSupport = false;
fOversizedStencilSupport = false;
fTextureBarrierSupport = false;
fSampleLocationsSupport = false;
fMultisampleDisableSupport = false;
fInstanceAttribSupport = false;
fUsesMixedSamples = false;
@ -154,6 +155,7 @@ void GrCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Gpu Tracing Support", fGpuTracingSupport);
writer->appendBool("Oversized Stencil Support", fOversizedStencilSupport);
writer->appendBool("Texture Barrier Support", fTextureBarrierSupport);
writer->appendBool("Sample Locations Support", fSampleLocationsSupport);
writer->appendBool("Multisample disable support", fMultisampleDisableSupport);
writer->appendBool("Instance Attrib Support", fInstanceAttribSupport);
writer->appendBool("Uses Mixed Samples", fUsesMixedSamples);

View File

@ -73,7 +73,7 @@ public:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

View File

@ -78,6 +78,8 @@ void GrFragmentProcessor::markPendingExecution() const {
}
int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child) {
this->combineRequiredFeatures(*child);
if (child->usesLocalCoords()) {
fFlags |= kUsesLocalCoords_Flag;
}

View File

@ -36,6 +36,7 @@ GrGpu::GrGpu(GrContext* context)
: fResetTimestamp(kExpiredTimestamp+1)
, fResetBits(kAll_GrBackendState)
, fContext(context) {
fMultisampleSpecs.emplace_back(0, 0, nullptr); // Index 0 is an invalid unique id.
}
GrGpu::~GrGpu() {}
@ -422,6 +423,48 @@ void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_
}
}
const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(const GrPipeline& pipeline) {
GrRenderTarget* rt = pipeline.renderTarget();
SkASSERT(rt->numStencilSamples() > 1);
GrStencilSettings stencil;
if (pipeline.isStencilEnabled()) {
// TODO: attach stencil and create settings during render target flush.
SkASSERT(rt->renderTargetPriv().getStencilAttachment());
stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
rt->renderTargetPriv().numStencilBits());
}
int effectiveSampleCnt;
SkSTArray<16, SkPoint, true> pattern;
this->onQueryMultisampleSpecs(rt, pipeline.proxy()->origin(), stencil,
&effectiveSampleCnt, &pattern);
SkASSERT(effectiveSampleCnt >= rt->numStencilSamples());
uint8_t id;
if (this->caps()->sampleLocationsSupport()) {
SkASSERT(pattern.count() == effectiveSampleCnt);
const auto& insertResult = fMultisampleSpecsIdMap.insert(
MultisampleSpecsIdMap::value_type(pattern, SkTMin(fMultisampleSpecs.count(), 255)));
id = insertResult.first->second;
if (insertResult.second) {
// This means the insert did not find the pattern in the map already, and therefore an
// actual insertion took place. (We don't expect to see many unique sample patterns.)
const SkPoint* sampleLocations = insertResult.first->first.begin();
SkASSERT(id == fMultisampleSpecs.count());
fMultisampleSpecs.emplace_back(id, effectiveSampleCnt, sampleLocations);
}
} else {
id = effectiveSampleCnt;
for (int i = fMultisampleSpecs.count(); i <= id; ++i) {
fMultisampleSpecs.emplace_back(i, i, nullptr);
}
}
SkASSERT(id > 0);
return fMultisampleSpecs[id];
}
bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a,
const SamplePattern& b) const {
if (a.count() != b.count()) {

View File

@ -328,6 +328,33 @@ public:
const SkIRect& srcRect,
const SkIPoint& dstPoint);
struct MultisampleSpecs {
MultisampleSpecs(uint8_t uniqueID, int effectiveSampleCnt, const SkPoint* locations)
: fUniqueID(uniqueID),
fEffectiveSampleCnt(effectiveSampleCnt),
fSampleLocations(locations) {}
// Nonzero ID that uniquely identifies these multisample specs.
uint8_t fUniqueID;
// The actual number of samples the GPU will run. NOTE: this value can be greater than the
// the render target's sample count.
int fEffectiveSampleCnt;
// If sample locations are supported, points to the subpixel locations at which the GPU will
// sample. Pixel center is at (.5, .5), and (0, 0) indicates the top left corner.
const SkPoint* fSampleLocations;
};
// Finds a render target's multisample specs. The pipeline is only needed in case we need to
// flush the draw state prior to querying multisample info. The pipeline is not expected to
// affect the multisample information itself.
const MultisampleSpecs& queryMultisampleSpecs(const GrPipeline&);
// Finds the multisample specs with a given unique id.
const MultisampleSpecs& getMultisampleSpecs(uint8_t uniqueID) {
SkASSERT(uniqueID > 0 && uniqueID < fMultisampleSpecs.count());
return fMultisampleSpecs[uniqueID];
}
// Creates a GrGpuRTCommandBuffer which GrOpLists send draw commands to instead of directly
// to the Gpu object.
virtual GrGpuRTCommandBuffer* createCommandBuffer(
@ -572,6 +599,11 @@ private:
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
// overridden by backend specific derived class to perform the multisample queries
virtual void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin rtOrigin,
const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) = 0;
virtual void onFinishFlush(bool insertedSemaphores) = 0;
virtual void onDumpJSON(SkJSONWriter*) const {}
@ -586,8 +618,12 @@ private:
bool operator()(const SamplePattern&, const SamplePattern&) const;
};
typedef std::map<SamplePattern, uint8_t, SamplePatternComparator> MultisampleSpecsIdMap;
ResetTimestamp fResetTimestamp;
uint32_t fResetBits;
MultisampleSpecsIdMap fMultisampleSpecsIdMap;
SkSTArray<1, MultisampleSpecs, true> fMultisampleSpecs;
// The context owns us, not vice-versa, so this ptr is not ref'ed by Gpu.
GrContext* fContext;

View File

@ -24,7 +24,7 @@ public:
}
void emitCode(EmitArgs& args) override {
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>();
if (!pathProc.viewMatrix().hasPerspective()) {

View File

@ -166,6 +166,18 @@ public:
return str;
}
/**
* Platform specific built-in features that a processor can request for the fragment shader.
*/
enum RequiredFeatures {
kNone_RequiredFeatures = 0,
kSampleLocations_RequiredFeature = 1 << 0
};
GR_DECL_BITFIELD_OPS_FRIENDS(RequiredFeatures);
RequiredFeatures requiredFeatures() const { return fRequiredFeatures; }
void* operator new(size_t size);
void operator delete(void* target);
@ -183,15 +195,30 @@ public:
protected:
GrProcessor(ClassID classID)
: fClassID(classID) {}
: fClassID(classID)
, fRequiredFeatures(kNone_RequiredFeatures) {}
/**
* If the prcoessor will generate code that uses platform specific built-in features, then it
* must call these methods from its constructor. Otherwise, requests to use these features will
* be denied.
*/
void setWillUseSampleLocations() { fRequiredFeatures |= kSampleLocations_RequiredFeature; }
void combineRequiredFeatures(const GrProcessor& other) {
fRequiredFeatures |= other.fRequiredFeatures;
}
private:
GrProcessor(const GrProcessor&) = delete;
GrProcessor& operator=(const GrProcessor&) = delete;
ClassID fClassID;
ClassID fClassID;
RequiredFeatures fRequiredFeatures;
};
GR_MAKE_BITFIELD_OPS(GrProcessor::RequiredFeatures);
/** A GrProcessor with the ability to access textures, buffers, and image storages. */
class GrResourceIOProcessor : public GrProcessor {
public:

View File

@ -169,6 +169,7 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
desc->key().reset();
return false;
}
GrProcessor::RequiredFeatures requiredFeatures = primProc.requiredFeatures();
for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
@ -176,6 +177,7 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
desc->key().reset();
return false;
}
requiredFeatures |= fp.requiredFeatures();
}
const GrXferProcessor& xp = pipeline.getXferProcessor();
@ -190,6 +192,7 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
desc->key().reset();
return false;
}
requiredFeatures |= xp.requiredFeatures();
// --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
// Because header is a pointer into the dynamic array, we can't push any new data into the key
@ -201,6 +204,16 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
GrRenderTargetProxy* proxy = pipeline.proxy();
if (requiredFeatures & GrProcessor::kSampleLocations_RequiredFeature) {
SkASSERT(pipeline.isHWAntialiasState());
GrRenderTarget* rt = pipeline.renderTarget();
header->fSamplePatternKey =
rt->renderTargetPriv().getMultisampleSpecs(pipeline).fUniqueID;
} else {
header->fSamplePatternKey = 0;
}
header->fOutputSwizzle = shaderCaps.configOutputSwizzle(proxy->config()).asKey();
header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();

View File

@ -81,13 +81,9 @@ public:
return !(*this == other);
}
void setSurfaceOriginKey(GrSurfaceOrigin origin) {
SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
void setSurfaceOriginKey(int key) {
KeyHeader* header = this->atOffset<KeyHeader, kHeaderOffset>();
header->fSurfaceOriginKey = origin;
GR_STATIC_ASSERT(0 == kTopLeft_GrSurfaceOrigin);
GR_STATIC_ASSERT(1 == kBottomLeft_GrSurfaceOrigin);
header->fSurfaceOriginKey = key;
}
static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) {
@ -104,15 +100,18 @@ public:
}
struct KeyHeader {
// Set to uniquely identify the sample pattern, or 0 if the shader doesn't use sample
// locations.
uint8_t fSamplePatternKey;
// Set to uniquely idenitify any swizzling of the shader's output color(s).
uint8_t fOutputSwizzle;
uint8_t fColorFragmentProcessorCnt; // Can be packed to 4 bits if required.
uint8_t fCoverageFragmentProcessorCnt;
uint8_t fOutputSwizzle;
uint8_t fColorFragmentProcessorCnt : 4;
uint8_t fCoverageFragmentProcessorCnt : 4;
// Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
bool fSurfaceOriginKey : 1; // Can be packed to 2 bits if required.
bool fSnapVerticesToPixelCenters : 1;
bool fHasPointSize : 1;
uint8_t fPad : 5;
uint8_t fSurfaceOriginKey : 2;
uint8_t fSnapVerticesToPixelCenters : 1;
uint8_t fHasPointSize : 1;
uint8_t fPad : 4;
};
GR_STATIC_ASSERT(sizeof(KeyHeader) == 4);

View File

@ -24,6 +24,7 @@ GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
: INHERITED(gpu, desc)
, fSampleCnt(desc.fSampleCnt)
, fStencilAttachment(stencil)
, fMultisampleSpecsID(0)
, fFlags(flags) {
SkASSERT(desc.fFlags & kRenderTarget_GrSurfaceFlag);
SkASSERT(!(fFlags & GrRenderTargetFlags::kMixedSampled) || fSampleCnt > 0);
@ -93,3 +94,16 @@ int GrRenderTargetPriv::numStencilBits() const {
return this->getStencilAttachment()->bits();
}
const GrGpu::MultisampleSpecs&
GrRenderTargetPriv::getMultisampleSpecs(const GrPipeline& pipeline) const {
SkASSERT(fRenderTarget == pipeline.renderTarget()); // TODO: remove RT from pipeline.
GrGpu* gpu = fRenderTarget->getGpu();
if (auto id = fRenderTarget->fMultisampleSpecsID) {
SkASSERT(gpu->queryMultisampleSpecs(pipeline).fUniqueID == id);
return gpu->getMultisampleSpecs(id);
}
const GrGpu::MultisampleSpecs& specs = gpu->queryMultisampleSpecs(pipeline);
fRenderTarget->fMultisampleSpecsID = specs.fUniqueID;
return specs;
}

View File

@ -32,6 +32,11 @@ public:
int numStencilBits() const;
// Finds a render target's multisample specs. The pipeline is only needed in case the info isn't
// cached and we need to flush the draw state in order to query it. The pipeline is not expected
// to affect the multisample information itself.
const GrGpu::MultisampleSpecs& getMultisampleSpecs(const GrPipeline&) const;
GrRenderTargetFlags flags() const { return fRenderTarget->fFlags; }
private:

View File

@ -43,6 +43,9 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fFlatInterpolationSupport = false;
fPreferFlatInterpolation = false;
fNoPerspectiveInterpolationSupport = false;
fMultisampleInterpolationSupport = false;
fSampleVariablesSupport = false;
fSampleMaskOverrideCoverageSupport = false;
fExternalTextureSupport = false;
fTexelFetchSupport = false;
fVertexIDSupport = false;
@ -58,6 +61,8 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fExternalTextureExtensionString = nullptr;
fTexelBufferExtensionString = nullptr;
fNoPerspectiveInterpolationExtensionString = nullptr;
fMultisampleInterpolationExtensionString = nullptr;
fSampleVariablesExtensionString = nullptr;
fFBFetchColorName = nullptr;
fFBFetchExtensionString = nullptr;
fImageLoadStoreExtensionString = nullptr;
@ -115,6 +120,9 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Flat interpolation support", fFlatInterpolationSupport);
writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation);
writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport);
writer->appendBool("Multisample interpolation support", fMultisampleInterpolationSupport);
writer->appendBool("Sample variables support", fSampleVariablesSupport);
writer->appendBool("Sample mask override coverage support", fSampleMaskOverrideCoverageSupport);
writer->appendBool("External texture support", fExternalTextureSupport);
writer->appendBool("texelFetch support", fTexelFetchSupport);
writer->appendBool("sk_VertexID support", fVertexIDSupport);

View File

@ -30,7 +30,7 @@ void GrCCCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHa
}
void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
GrGLSLFragmentBuilder* f,
GrGLSLPPFragmentBuilder* f,
const char* skOutputColor,
const char* skOutputCoverage) const {
f->codeAppendf("half coverage = 0;");
@ -62,7 +62,7 @@ void GrCCCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuil
s->codeAppendf("%s = float3(-n, dot(n, %s) - .5);", outputDistanceEquation, leftPt);
}
int GrCCCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLFragmentBuilder* f,
int GrCCCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f,
const char* samplesName) {
// Standard DX11 sample locations.
#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)

View File

@ -15,7 +15,7 @@
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLVarying.h"
class GrGLSLFragmentBuilder;
class GrGLSLPPFragmentBuilder;
class GrGLSLVertexGeoBuilder;
class GrMesh;
@ -165,7 +165,7 @@ public:
void emitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage, const char* wind);
void emitFragmentCode(const GrCCCoverageProcessor& proc, GrGLSLFragmentBuilder*,
void emitFragmentCode(const GrCCCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
const char* skOutputColor, const char* skOutputCoverage) const;
// Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
@ -197,7 +197,7 @@ public:
// Emits the fragment code that calculates a pixel's coverage value. If using
// WindHandling::kHandled, this value must be signed appropriately.
virtual void onEmitFragmentCode(GrGLSLFragmentBuilder*,
virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
const char* outputCoverage) const = 0;
// Returns the name of a Shader's internal varying at the point where where its value is
@ -212,7 +212,7 @@ public:
// center. Subclasses can use this for software multisampling.
//
// Returns the number of samples.
static int DefineSoftSampleLocations(GrGLSLFragmentBuilder* f, const char* samplesName);
static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
private:
GrGLSLVarying fWind;

View File

@ -101,7 +101,7 @@ void GrCCCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
OutName(fGradMatrix), fKLMMatrix.c_str(), fKLMMatrix.c_str());
}
void GrCCCubicHullShader::onEmitFragmentCode(GrGLSLFragmentBuilder* f,
void GrCCCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const {
f->codeAppendf("float k = %s.x, l = %s.y, m = %s.z, d = %s.w;",
fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
@ -132,7 +132,7 @@ void GrCCCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
}
void GrCCCubicCornerShader::onEmitFragmentCode(GrGLSLFragmentBuilder* f,
void GrCCCubicCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const {
f->codeAppendf("float2x4 grad_klmd = float2x4(%s, %s);", fdKLMDdx.fsIn(), fdKLMDdy.fsIn());

View File

@ -41,7 +41,7 @@ protected:
class GrCCCubicHullShader : public GrCCCubicShader {
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
GrGLSLVarying fGradMatrix;
};
@ -50,7 +50,7 @@ class GrCCCubicCornerShader : public GrCCCubicShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
GrGLSLVarying fdKLMDdx;
GrGLSLVarying fdKLMDdy;

View File

@ -217,7 +217,7 @@ void GLSLPathProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
args.fFPCoordTransformHandler);
// Fragment shader.
GrGLSLFragmentBuilder* f = args.fFragBuilder;
GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
f->codeAppend ("half coverage_count = ");
f->appendTextureLookup(args.fTexSamplers[0], texcoord.fsIn(), kFloat2_GrSLType);

View File

@ -79,7 +79,7 @@ void GrCCQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandle
OutName(fGrad), OutName(fXYD), fCanonicalMatrix.c_str());
}
void GrCCQuadraticHullShader::onEmitFragmentCode(GrGLSLFragmentBuilder* f,
void GrCCQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const {
f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s, %s));",
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn(), fGrad.fsIn(), fGrad.fsIn());
@ -109,7 +109,7 @@ void GrCCQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHand
fEdgeDistanceEquation.c_str());
}
void GrCCQuadraticCornerShader::onEmitFragmentCode(GrGLSLFragmentBuilder* f,
void GrCCQuadraticCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const {
f->codeAppendf("float x = %s.x, y = %s.y, d = %s.z;",
fXYD.fsIn(), fXYD.fsIn(), fXYD.fsIn());

View File

@ -48,7 +48,7 @@ class GrCCQuadraticHullShader : public GrCCQuadraticShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
GrGLSLVarying fGrad;
};
@ -60,7 +60,7 @@ class GrCCQuadraticCornerShader : public GrCCQuadraticShader {
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
GeometryVars*) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
void onEmitFragmentCode(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
GrGLSLVarying fdXYDdx;
GrGLSLVarying fdXYDdy;

View File

@ -27,7 +27,7 @@ Shader::WindHandling GrCCTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* va
return WindHandling::kHandled;
}
void GrCCTriangleShader::onEmitFragmentCode(GrGLSLFragmentBuilder* f,
void GrCCTriangleShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const {
f->codeAppendf("%s = %s;", outputCoverage, fCoverageTimesWind.fsIn());
}
@ -109,7 +109,7 @@ GrCCTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
return WindHandling::kNotHandled;
}
void GrCCTriangleCornerShader::onEmitFragmentCode(GrGLSLFragmentBuilder* f,
void GrCCTriangleCornerShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
const char* outputCoverage) const {
// By the time we reach this shader, the pixel is in the following state:
//

View File

@ -20,7 +20,7 @@ class GrCCTriangleShader : public GrCCCoverageProcessor::Shader {
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage,
const char* wind) override;
void onEmitFragmentCode(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
GrGLSLVarying fCoverageTimesWind;
};
@ -36,7 +36,7 @@ class GrCCTriangleCornerShader : public GrCCCoverageProcessor::Shader {
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage,
const char* wind) override;
void onEmitFragmentCode(GrGLSLFragmentBuilder* f, const char* outputCoverage) const override;
void onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, const char* outputCoverage) const override;
GrShaderVar fAABoxMatrices{"aa_box_matrices", kFloat2x2_GrSLType, 2};
GrShaderVar fAABoxTranslates{"aa_box_translates", kFloat2_GrSLType, 2};

View File

@ -43,6 +43,12 @@ public:
return true;
}
void onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override {
SkASSERT(0);
*effectiveSampleCnt = 0; // ??
}
GrGpuRTCommandBuffer* createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,

View File

@ -81,7 +81,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
varyingHandler->addVarying("ConicCoeffs", &v);
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup pass through color
this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
@ -333,7 +333,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
varyingHandler->addVarying("HairQuadEdge", &v);
vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup pass through color
this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
@ -534,7 +534,7 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// emit attributes
varyingHandler->emitAttributes(gp);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup pass through color
if (!gp.colorIgnored()) {
this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);

View File

@ -43,7 +43,7 @@ public:
append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, nullptr);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup pass through color
if (btgp.hasVertexColor()) {
varyingHandler->addPassThroughAttribute(btgp.inColor(), args.fOutputColor);

View File

@ -27,7 +27,7 @@ public:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const GrDistanceFieldA8TextGeoProc& dfTexEffect =
args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
@ -309,7 +309,7 @@ public:
const GrDistanceFieldPathGeoProc& dfPathEffect =
args.fGP.cast<GrDistanceFieldPathGeoProc>();
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
@ -592,7 +592,7 @@ public:
"AtlasSizeInv",
&atlasSizeInvName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// setup pass through color
varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);

View File

@ -22,7 +22,7 @@ public:
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// emit attributes
varyingHandler->emitAttributes(rsgp);

View File

@ -117,6 +117,13 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
fTextureBarrierSupport = ctxInfo.hasExtension("GL_NV_texture_barrier");
}
if (kGL_GrGLStandard == standard) {
fSampleLocationsSupport = version >= GR_GL_VER(3,2) ||
ctxInfo.hasExtension("GL_ARB_texture_multisample");
} else {
fSampleLocationsSupport = version >= GR_GL_VER(3,1);
}
fImagingSupport = kGL_GrGLStandard == standard &&
ctxInfo.hasExtension("GL_ARB_imaging");
@ -723,6 +730,35 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
}
}
if (kGL_GrGLStandard == standard) {
shaderCaps->fMultisampleInterpolationSupport =
ctxInfo.glslGeneration() >= k400_GrGLSLGeneration;
} else {
if (ctxInfo.glslGeneration() >= k320es_GrGLSLGeneration) {
shaderCaps->fMultisampleInterpolationSupport = true;
} else if (ctxInfo.hasExtension("GL_OES_shader_multisample_interpolation")) {
shaderCaps->fMultisampleInterpolationSupport = true;
shaderCaps->fMultisampleInterpolationExtensionString =
"GL_OES_shader_multisample_interpolation";
}
}
if (kGL_GrGLStandard == standard) {
shaderCaps->fSampleVariablesSupport = ctxInfo.glslGeneration() >= k400_GrGLSLGeneration;
} else {
if (ctxInfo.glslGeneration() >= k320es_GrGLSLGeneration) {
shaderCaps->fSampleVariablesSupport = true;
} else if (ctxInfo.hasExtension("GL_OES_sample_variables")) {
shaderCaps->fSampleVariablesSupport = true;
shaderCaps->fSampleVariablesExtensionString = "GL_OES_sample_variables";
}
}
if (shaderCaps->fSampleVariablesSupport &&
ctxInfo.hasExtension("GL_NV_sample_mask_override_coverage")) {
shaderCaps->fSampleMaskOverrideCoverageSupport = true;
}
shaderCaps->fVersionDeclString = get_glsl_version_decl_string(standard,
shaderCaps->fGLSLGeneration,
fIsCoreProfile);
@ -2262,6 +2298,12 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
shaderCaps->fFBFetchSupport = false;
}
// Pre-361 NVIDIA has a bug with NV_sample_mask_override_coverage.
if (kNVIDIA_GrGLDriver == ctxInfo.driver() &&
ctxInfo.driverVersion() < GR_GL_DRIVER_VER(361,00)) {
shaderCaps->fSampleMaskOverrideCoverageSupport = false;
}
// Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
shaderCaps->fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();

View File

@ -4343,6 +4343,38 @@ bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin
return true;
}
void GrGLGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin rtOrigin,
const GrStencilSettings& stencil,
int* effectiveSampleCnt, SamplePattern* samplePattern) {
SkASSERT(GrFSAAType::kMixedSamples != rt->fsaaType() ||
rt->renderTargetPriv().getStencilAttachment() || stencil.isDisabled());
this->flushStencil(stencil);
this->flushHWAAState(rt, true, !stencil.isDisabled());
this->flushRenderTarget(static_cast<GrGLRenderTarget*>(rt), &SkIRect::EmptyIRect());
if (0 != this->caps()->maxRasterSamples()) {
GR_GL_GetIntegerv(this->glInterface(), GR_GL_EFFECTIVE_RASTER_SAMPLES, effectiveSampleCnt);
} else {
GR_GL_GetIntegerv(this->glInterface(), GR_GL_SAMPLES, effectiveSampleCnt);
}
SkASSERT(*effectiveSampleCnt >= rt->numStencilSamples());
if (this->caps()->sampleLocationsSupport()) {
samplePattern->reset(*effectiveSampleCnt);
for (int i = 0; i < *effectiveSampleCnt; ++i) {
GrGLfloat pos[2];
GL_CALL(GetMultisamplefv(GR_GL_SAMPLE_POSITION, i, pos));
if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
(*samplePattern)[i].set(pos[0], pos[1]);
} else {
(*samplePattern)[i].set(pos[0], 1 - pos[1]);
}
}
}
}
void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) {
SkASSERT(type);
switch (type) {

View File

@ -267,6 +267,9 @@ private:
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint) override;
void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override;
// binds texture unit in GL
void setTextureUnit(int unitIdx);

View File

@ -83,7 +83,7 @@ GrGLProgram* GrGLGpu::ProgramCache::refProgram(const GrGLGpu* gpu,
if (!entry) {
// Didn't find an origin-independent version, check with the specific origin
GrSurfaceOrigin origin = pipeline.proxy()->origin();
desc.setSurfaceOriginKey(origin);
desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
desc.finalize();
entry = fMap.find(desc);
}

View File

@ -98,7 +98,8 @@ bool GrGLProgramBuilder::compileAndAttachShaders(const char* glsl,
*shaderIds->append() = shaderId;
if (inputs.fFlipY) {
GrProgramDesc* d = this->desc();
d->setSurfaceOriginKey(this->pipeline().proxy()->origin());
d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
this->pipeline().proxy()->origin()));
d->finalize();
}

View File

@ -17,6 +17,18 @@
const char* GrGLSLFragmentShaderBuilder::kDstColorName = "_dstColor";
static const char* sample_offset_array_name(GrGLSLFPFragmentBuilder::Coordinates coords) {
static const char* kArrayNames[] = {
"deviceSpaceSampleOffsets",
"windowSpaceSampleOffsets"
};
return kArrayNames[coords];
GR_STATIC_ASSERT(0 == GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
GR_STATIC_ASSERT(1 == GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kArrayNames) == GrGLSLFPFragmentBuilder::kLast_Coordinates + 1);
}
static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
SkASSERT(GrBlendEquationIsAdvanced(equation));
@ -58,19 +70,47 @@ static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
}
uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin) {
SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
return origin + 1;
GR_STATIC_ASSERT(0 == kTopLeft_GrSurfaceOrigin);
GR_STATIC_ASSERT(1 == kBottomLeft_GrSurfaceOrigin);
}
GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
: GrGLSLFragmentBuilder(program)
, fSetupFragPosition(false)
, fHasCustomColorOutput(false)
, fCustomColorOutputIndex(-1)
, fHasSecondaryOutput(false)
, fUsedSampleOffsetArrays(0)
, fHasInitializedSampleMask(false)
, fForceHighPrecision(false) {
fSubstageIndices.push_back(0);
#ifdef SK_DEBUG
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
fHasReadDstColor = false;
#endif
}
bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
switch (feature) {
case kMultisampleInterpolation_GLSLFeature:
if (!shaderCaps.multisampleInterpolationSupport()) {
return false;
}
if (const char* extension = shaderCaps.multisampleInterpolationExtensionString()) {
this->addFeature(1 << kMultisampleInterpolation_GLSLFeature, extension);
}
return true;
default:
SK_ABORT("Unexpected GLSLFeature requested.");
return false;
}
}
SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
if (kFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
SkASSERT(kFloat2_GrSLType == coords.getType() || kHalf2_GrSLType == coords.getType());
@ -84,6 +124,57 @@ SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords)
return coords2D;
}
void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Coordinates coords) {
SkASSERT(fProgramBuilder->header().fSamplePatternKey);
SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_RequiredFeature);
if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
// With a top left origin, device and window space are equal, so we only use device coords.
coords = kSkiaDevice_Coordinates;
}
this->codeAppendf("%s[%s]", sample_offset_array_name(coords), sampleIdx);
fUsedSampleOffsetArrays |= (1 << coords);
}
void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) {
const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
if (!shaderCaps.sampleVariablesSupport()) {
SkDEBUGFAIL("Attempted to mask sample coverage without support.");
return;
}
if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
}
if (!fHasInitializedSampleMask) {
this->codePrependf("gl_SampleMask[0] = -1;");
fHasInitializedSampleMask = true;
}
if (invert) {
this->codeAppendf("gl_SampleMask[0] &= ~(%s);", mask);
} else {
this->codeAppendf("gl_SampleMask[0] &= %s;", mask);
}
}
void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) {
const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
if (!shaderCaps.sampleMaskOverrideCoverageSupport()) {
SkDEBUGFAIL("Attempted to override sample coverage without support.");
return;
}
SkASSERT(shaderCaps.sampleVariablesSupport());
if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
}
if (this->addFeature(1 << kSampleMaskOverrideCoverage_GLSLPrivateFeature,
"GL_NV_sample_mask_override_coverage")) {
// Redeclare gl_SampleMask with layout(override_coverage) if we haven't already.
fOutputs.push_back().set(kInt_GrSLType, "gl_SampleMask", 1, GrShaderVar::kOut_TypeModifier,
kHigh_GrSLPrecision, "override_coverage");
}
this->codeAppendf("gl_SampleMask[0] = %s;", mask);
fHasInitializedSampleMask = true;
}
const char* GrGLSLFragmentShaderBuilder::dstColor() {
SkDEBUGCODE(fHasReadDstColor = true;)
@ -185,6 +276,33 @@ GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
void GrGLSLFragmentShaderBuilder::onFinalize() {
fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
SkMatrix::MakeTrans(-0.5f, -0.5f));
}
if (fUsedSampleOffsetArrays & (1 << kGLSLWindow_Coordinates)) {
// With a top left origin, device and window space are equal, so we only use device coords.
SkASSERT(kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin());
SkMatrix m;
m.setScale(1, -1);
m.preTranslate(-0.5f, -0.5f);
this->defineSampleOffsetArray(sample_offset_array_name(kGLSLWindow_Coordinates), m);
}
}
void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, const SkMatrix& m) {
SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport());
const GrPipeline& pipeline = fProgramBuilder->pipeline();
const GrRenderTargetPriv& rtp = pipeline.renderTarget()->renderTargetPriv();
const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
SkSTArray<16, SkPoint, true> offsets;
offsets.push_back_n(specs.fEffectiveSampleCnt);
m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt);
this->definitions().appendf("const float2 %s[] = float2[](", name);
for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
this->definitions().appendf("float2(%f, %f)", offsets[i].x(), offsets[i].y());
this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
}
}
void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() {

View File

@ -24,6 +24,20 @@ public:
GrGLSLFragmentBuilder(GrGLSLProgramBuilder* program) : INHERITED(program) {}
virtual ~GrGLSLFragmentBuilder() {}
/**
* Use of these features may require a GLSL extension to be enabled. Shaders may not compile
* if code is added that uses one of these features without calling enableFeature()
*/
enum GLSLFeature {
kMultisampleInterpolation_GLSLFeature
};
/**
* If the feature is supported then true is returned and any necessary #extension declarations
* are added to the shaders. If the feature is not supported then false will be returned.
*/
virtual bool enableFeature(GLSLFeature) = 0;
/**
* This returns a variable name to access the 2D, perspective correct version of the coords in
* the fragment shader. The passed in coordinates must either be of type kHalf2 or kHalf3. If
@ -47,6 +61,34 @@ public:
/** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
GrGLSLFPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
enum Coordinates {
kSkiaDevice_Coordinates,
kGLSLWindow_Coordinates,
kLast_Coordinates = kGLSLWindow_Coordinates
};
/**
* Appends the offset from the center of the pixel to a specified sample.
*
* @param sampleIdx GLSL expression of the sample index.
* @param Coordinates Coordinate space in which to emit the offset.
*
* A processor must call setWillUseSampleLocations in its constructor before using this method.
*/
virtual void appendOffsetToSample(const char* sampleIdx, Coordinates) = 0;
/**
* Subtracts sample coverage from the fragment. Any sample whose corresponding bit is not found
* in the mask will not be written out to the framebuffer.
*
* @param mask int that contains the sample mask. Bit N corresponds to the Nth sample.
* @param invert perform a bit-wise NOT on the provided mask before applying it?
*
* Requires GLSL support for sample variables.
*/
virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0;
/**
* Fragment procs with child procs should call these functions before/after calling emitCode
* on a child proc.
@ -59,6 +101,29 @@ public:
virtual void forceHighPrecision() = 0;
};
/*
* This class is used by primitive processors to build their fragment code.
*/
class GrGLSLPPFragmentBuilder : public GrGLSLFPFragmentBuilder {
public:
/** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
GrGLSLPPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
/**
* Overrides the fragment's sample coverage. The provided mask determines which samples will now
* be written out to the framebuffer. Note that this mask can be reduced by a future call to
* maskSampleCoverage.
*
* If a primitive processor uses this method, it must guarantee that every codepath through the
* shader overrides the sample mask at some point.
*
* @param mask int that contains the new coverage mask. Bit N corresponds to the Nth sample.
*
* Requires NV_sample_mask_override_coverage.
*/
virtual void overrideSampleCoverage(const char* mask) = 0;
};
/*
* This class is used by Xfer processors to build their fragment code.
*/
@ -83,14 +148,22 @@ public:
/*
* This class implements the various fragment builder interfaces.
*/
class GrGLSLFragmentShaderBuilder : public GrGLSLFPFragmentBuilder, public GrGLSLXPFragmentBuilder {
class GrGLSLFragmentShaderBuilder : public GrGLSLPPFragmentBuilder, public GrGLSLXPFragmentBuilder {
public:
/** Returns a nonzero key for a surface's origin. This should only be called if a processor will
use the fragment position and/or sample locations. */
static uint8_t KeyForSurfaceOrigin(GrSurfaceOrigin);
GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program);
// Shared GrGLSLFragmentBuilder interface.
bool enableFeature(GLSLFeature) override;
virtual SkString ensureCoords2D(const GrShaderVar&) override;
// GrGLSLFPFragmentBuilder interface.
void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
void maskSampleCoverage(const char* mask, bool invert = false) override;
void overrideSampleCoverage(const char* mask) override;
const SkString& getMangleString() const override { return fMangleString; }
void onBeforeChildProcEmitCode() override;
void onAfterChildProcEmitCode() override;
@ -112,8 +185,10 @@ private:
#ifdef SK_DEBUG
// As GLSLProcessors emit code, there are some conditions we need to verify. We use the below
// state to track this. The reset call is called per processor emitted.
GrProcessor::RequiredFeatures usedProcessorFeatures() const { return fUsedProcessorFeatures; }
bool hasReadDstColor() const { return fHasReadDstColor; }
void resetVerification() {
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
fHasReadDstColor = false;
}
#endif
@ -124,6 +199,7 @@ private:
GrSurfaceOrigin getSurfaceOrigin() const;
void onFinalize() override;
void defineSampleOffsetArray(const char* name, const SkMatrix&);
static const char* kDstColorName;
@ -151,11 +227,14 @@ private:
bool fHasCustomColorOutput;
int fCustomColorOutputIndex;
bool fHasSecondaryOutput;
uint8_t fUsedSampleOffsetArrays;
bool fHasInitializedSampleMask;
bool fForceHighPrecision;
#ifdef SK_DEBUG
// some state to verify shaders and effects are consistent, this is reset between effects by
// the program creator
GrProcessor::RequiredFeatures fUsedProcessorFeatures;
bool fHasReadDstColor;
#endif

View File

@ -36,7 +36,7 @@ SkMatrix GrGLSLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatri
return combined;
}
void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLFragmentBuilder* fragBuilder,
void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLPPFragmentBuilder* fragBuilder,
GrGLSLUniformHandler* uniformHandler,
const char* outputName,
UniformHandle* colorUniform) {

View File

@ -14,7 +14,7 @@
#include "glsl/GrGLSLUniformHandler.h"
class GrPrimitiveProcessor;
class GrGLSLFragmentBuilder;
class GrGLSLPPFragmentBuilder;
class GrGLSLGeometryBuilder;
class GrGLSLGPBuilder;
class GrGLSLVaryingHandler;
@ -67,7 +67,7 @@ public:
struct EmitArgs {
EmitArgs(GrGLSLVertexBuilder* vertBuilder,
GrGLSLGeometryBuilder* geomBuilder,
GrGLSLFragmentBuilder* fragBuilder,
GrGLSLPPFragmentBuilder* fragBuilder,
GrGLSLVaryingHandler* varyingHandler,
GrGLSLUniformHandler* uniformHandler,
const GrShaderCaps* caps,
@ -93,7 +93,7 @@ public:
, fFPCoordTransformHandler(transformHandler) {}
GrGLSLVertexBuilder* fVertBuilder;
GrGLSLGeometryBuilder* fGeomBuilder;
GrGLSLFragmentBuilder* fFragBuilder;
GrGLSLPPFragmentBuilder* fFragBuilder;
GrGLSLVaryingHandler* fVaryingHandler;
GrGLSLUniformHandler* fUniformHandler;
const GrShaderCaps* fShaderCaps;
@ -129,7 +129,7 @@ public:
static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
protected:
void setupUniformColor(GrGLSLFragmentBuilder* fragBuilder,
void setupUniformColor(GrGLSLPPFragmentBuilder* fragBuilder,
GrGLSLUniformHandler* uniformHandler,
const char* outputName,
UniformHandle* colorUniform);

View File

@ -360,13 +360,16 @@ bool GrGLSLProgramBuilder::checkSamplerCounts() {
#ifdef SK_DEBUG
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
}
void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
}
void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
}
#endif

View File

@ -173,7 +173,9 @@ protected:
kTexelBuffer_GLSLPrivateFeature,
kFramebufferFetch_GLSLPrivateFeature,
kNoPerspectiveInterpolation_GLSLPrivateFeature,
kLastGLSLPrivateFeature = kNoPerspectiveInterpolation_GLSLPrivateFeature
kSampleVariables_GLSLPrivateFeature,
kSampleMaskOverrideCoverage_GLSLPrivateFeature,
kLastGLSLPrivateFeature = kSampleMaskOverrideCoverage_GLSLPrivateFeature
};
/*

View File

@ -39,6 +39,11 @@ public:
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint) override { return true; }
void onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override {
*effectiveSampleCnt = rt->numStencilSamples();
}
GrGpuRTCommandBuffer* createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,

View File

@ -150,6 +150,7 @@ void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
fTextureBarrierSupport = false; // Need to figure out if we can do this
fSampleLocationsSupport = false;
fMultisampleDisableSupport = false;
if (this->isMac() || 3 == fFamilyGroup) {

View File

@ -46,6 +46,9 @@ public:
const SkIRect& srcRect,
const SkIPoint& dstPoint) override { return false; }
void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override {}
GrGpuRTCommandBuffer* createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,

View File

@ -573,7 +573,7 @@ public:
// Setup pass through color
varyingHandler->addPassThroughAttribute(qe.fInColor, args.fOutputColor);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, qe.fInPosition->fName);

View File

@ -919,7 +919,7 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
varyingHandler->addVarying("CircleParams", &circleParams);
vertBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->fName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup pass through color
this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
@ -1122,7 +1122,7 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
varyingHandler->addVarying("RectParams", &inRectParams);
vertBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->fName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Setup pass through color
this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);

View File

@ -153,7 +153,7 @@ public:
qp.inPosition()->asShaderVar(), SkMatrix::I(),
args.fFPCoordTransformHandler);
GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
uv.fsIn());
fsBuilder->codeAppendf("%s = half4(1.0);", args.fOutputCoverage);

View File

@ -113,7 +113,7 @@ private:
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// emit attributes
varyingHandler->emitAttributes(cgp);
@ -281,7 +281,7 @@ private:
varyingHandler->addVarying("EllipseRadii", &ellipseRadii);
vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii->fName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
// setup pass through color
varyingHandler->addPassThroughAttribute(egp.fInColor, args.fOutputColor);
@ -420,7 +420,7 @@ private:
varyingHandler->addVarying("EllipseOffsets1", &offsets1);
vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), diegp.fInEllipseOffsets1->fName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
varyingHandler->addPassThroughAttribute(diegp.fInColor, args.fOutputColor);
// Setup position

View File

@ -1879,6 +1879,13 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
return false;
}
void GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) {
// TODO: stub.
SkASSERT(!this->caps()->sampleLocationsSupport());
*effectiveSampleCnt = rt->numStencilSamples();
}
bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
int width, int height, size_t rowBytes,
GrPixelConfig readConfig, DrawPreference* drawPreference,

View File

@ -78,6 +78,9 @@ public:
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint) override;
void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override;
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h,

View File

@ -79,7 +79,8 @@ bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
}
if (inputs.fFlipY) {
desc->setSurfaceOriginKey(this->pipeline().proxy()->origin());
desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
this->pipeline().proxy()->origin()));
desc->finalize();
}
return result;

View File

@ -103,7 +103,7 @@ GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState(
if (!entry) {
// Didn't find an origin-independent version, check with the specific origin
GrSurfaceOrigin origin = pipeline.proxy()->origin();
desc.setSurfaceOriginKey(origin);
desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
desc.finalize();
entry = fMap.find(desc);
}

View File

@ -130,6 +130,9 @@ static void fill_caps(const SKSL_CAPS_CLASS& caps,
CAP(dropsTileOnZeroDivide);
CAP(flatInterpolationSupport);
CAP(noperspectiveInterpolationSupport);
CAP(multisampleInterpolationSupport);
CAP(sampleVariablesSupport);
CAP(sampleMaskOverrideCoverageSupport);
CAP(externalTextureSupport);
CAP(texelFetchSupport);
CAP(imageLoadStoreSupport);

View File

@ -99,6 +99,18 @@ public:
return true;
}
bool multisampleInterpolationSupport() const {
return true;
}
bool sampleVariablesSupport() const {
return true;
}
bool sampleMaskOverrideCoverageSupport() const {
return true;
}
bool externalTextureSupport() const {
return true;
}

View File

@ -0,0 +1,199 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkTypes.h"
#include "SkPoint.h"
#include "Test.h"
#include <vector>
#if SK_SUPPORT_GPU
#include "GrAppliedClip.h"
#include "GrRenderTargetContext.h"
#include "GrRenderTargetPriv.h"
#include "GrTypesPriv.h"
#include "gl/GrGLGpu.h"
#include "gl/debug/DebugGLTestContext.h"
typedef std::vector<SkPoint> SamplePattern;
static const SamplePattern kTestPatterns[] = {
SamplePattern{ // Intel on mac, msaa8, offscreen.
{0.562500, 0.312500},
{0.437500, 0.687500},
{0.812500, 0.562500},
{0.312500, 0.187500},
{0.187500, 0.812500},
{0.062500, 0.437500},
{0.687500, 0.937500},
{0.937500, 0.062500}
},
SamplePattern{ // Intel on mac, msaa8, on-screen.
{0.562500, 0.687500},
{0.437500, 0.312500},
{0.812500, 0.437500},
{0.312500, 0.812500},
{0.187500, 0.187500},
{0.062500, 0.562500},
{0.687500, 0.062500},
{0.937500, 0.937500}
},
SamplePattern{ // NVIDIA, msaa16.
{0.062500, 0.000000},
{0.250000, 0.125000},
{0.187500, 0.375000},
{0.437500, 0.312500},
{0.500000, 0.062500},
{0.687500, 0.187500},
{0.750000, 0.437500},
{0.937500, 0.250000},
{0.000000, 0.500000},
{0.312500, 0.625000},
{0.125000, 0.750000},
{0.375000, 0.875000},
{0.562500, 0.562500},
{0.812500, 0.687500},
{0.625000, 0.812500},
{0.875000, 0.937500}
},
SamplePattern{ // NVIDIA, mixed samples, 16:1.
{0.250000, 0.125000},
{0.625000, 0.812500},
{0.500000, 0.062500},
{0.812500, 0.687500},
{0.187500, 0.375000},
{0.875000, 0.937500},
{0.125000, 0.750000},
{0.750000, 0.437500},
{0.937500, 0.250000},
{0.312500, 0.625000},
{0.437500, 0.312500},
{0.000000, 0.500000},
{0.375000, 0.875000},
{0.687500, 0.187500},
{0.062500, 0.000000},
{0.562500, 0.562500}
}
};
constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns);
class TestSampleLocationsInterface : public SkNoncopyable {
public:
virtual void overrideSamplePattern(const SamplePattern&) = 0;
virtual ~TestSampleLocationsInterface() {}
};
void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
const GrGpu::MultisampleSpecs& specs, bool flipY) {
GrAlwaysAssert(specs.fSampleLocations);
if ((int)pattern.size() != specs.fEffectiveSampleCnt) {
REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong number of samples."));
return;
}
for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
SkPoint expectedLocation = specs.fSampleLocations[i];
if (flipY) {
expectedLocation.fY = 1 - expectedLocation.fY;
}
if (pattern[i] != expectedLocation) {
REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong sample location."));
return;
}
}
}
void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInterface* testInterface,
GrContext* ctx) {
SkRandom rand;
sk_sp<GrRenderTargetContext> bottomUps[numTestPatterns];
sk_sp<GrRenderTargetContext> topDowns[numTestPatterns];
for (int i = 0; i < numTestPatterns; ++i) {
int numSamples = (int)kTestPatterns[i].size();
GrAlwaysAssert(numSamples > 1 && SkIsPow2(numSamples));
bottomUps[i] = ctx->makeDeferredRenderTargetContext(
SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
rand.nextRangeU(1 + numSamples / 2, numSamples), GrMipMapped::kNo,
kBottomLeft_GrSurfaceOrigin);
topDowns[i] = ctx->makeDeferredRenderTargetContext(
SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
rand.nextRangeU(1 + numSamples / 2, numSamples), GrMipMapped::kNo,
kTopLeft_GrSurfaceOrigin);
}
// Ensure all sample locations get queried and/or cached properly.
for (int repeat = 0; repeat < 2; ++repeat) {
for (int i = 0; i < numTestPatterns; ++i) {
testInterface->overrideSamplePattern(kTestPatterns[i]);
for (GrRenderTargetContext* rtc : {bottomUps[i].get(), topDowns[i].get()}) {
GrPipeline dummyPipeline(rtc->asRenderTargetProxy(),
GrPipeline::ScissorState::kDisabled,
SkBlendMode::kSrcOver);
GrRenderTarget* rt = rtc->accessRenderTarget();
assert_equal(reporter, kTestPatterns[i],
rt->renderTargetPriv().getMultisampleSpecs(dummyPipeline),
kBottomLeft_GrSurfaceOrigin == rtc->asSurfaceProxy()->origin());
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface {
public:
GLTestSampleLocationsInterface() : fTestContext(sk_gpu_test::CreateDebugGLTestContext()) {
fStandard = fTestContext->gl()->fStandard;
fExtensions = fTestContext->gl()->fExtensions;
fFunctions = fTestContext->gl()->fFunctions;
fFunctions.fGetIntegerv = [&](GrGLenum pname, GrGLint* params) {
GrAlwaysAssert(GR_GL_EFFECTIVE_RASTER_SAMPLES != pname);
if (GR_GL_SAMPLES == pname) {
GrAlwaysAssert(!fSamplePattern.empty());
*params = (int)fSamplePattern.size();
} else {
fTestContext->gl()->fFunctions.fGetIntegerv(pname, params);
}
};
fFunctions.fGetMultisamplefv = [&](GrGLenum pname, GrGLuint index, GrGLfloat* val) {
GrAlwaysAssert(GR_GL_SAMPLE_POSITION == pname);
val[0] = fSamplePattern[index].fX;
val[1] = fSamplePattern[index].fY;
};
}
operator GrBackendContext() {
return reinterpret_cast<GrBackendContext>(static_cast<GrGLInterface*>(this));
}
void overrideSamplePattern(const SamplePattern& newPattern) override {
fSamplePattern = newPattern;
}
private:
std::unique_ptr<sk_gpu_test::GLTestContext> fTestContext;
SamplePattern fSamplePattern;
};
DEF_GPUTEST(GLSampleLocations, reporter, /* options */) {
auto testInterface = sk_make_sp<GLTestSampleLocationsInterface>();
sk_sp<GrContext> ctx(GrContext::MakeGL(testInterface));
// This test relies on at least 2 samples.
int supportedSample = ctx->caps()->getSampleCount(2, kRGBA_8888_GrPixelConfig);
if (supportedSample < 2) {
return;
}
test_sampleLocations(reporter, testInterface.get(), ctx.get());
}
#endif

View File

@ -341,7 +341,7 @@ class GLSLMeshTestProcessor : public GrGLSLGeometryProcessor {
}
gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
GrGLSLFragmentBuilder* f = args.fFragBuilder;
GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
}
};

View File

@ -93,7 +93,7 @@ class GLSLPipelineDynamicStateTestProcessor : public GrGLSLGeometryProcessor {
v->codeAppendf("float2 vertex = %s;", mp.fVertex.fName);
gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
GrGLSLFragmentBuilder* f = args.fFragBuilder;
GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
}
};

View File

@ -73,7 +73,7 @@ private:
const GP& gp = args.fGP.cast<GP>();
args.fVaryingHandler->emitAttributes(gp);
this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.getAttrib(0).fName);
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputColor);
fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
}