Drop unused support for MSAA sample locations
Bug: skia: Change-Id: I96f0c25732d79c5881e400b121e81c5696a747a6 Reviewed-on: https://skia-review.googlesource.com/107441 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
cfac205c5e
commit
535ba8d2b8
@ -89,7 +89,6 @@ tests_sources = [
|
|||||||
"$_tests/GpuDrawPathTest.cpp",
|
"$_tests/GpuDrawPathTest.cpp",
|
||||||
"$_tests/GpuLayerCacheTest.cpp",
|
"$_tests/GpuLayerCacheTest.cpp",
|
||||||
"$_tests/GpuRectanizerTest.cpp",
|
"$_tests/GpuRectanizerTest.cpp",
|
||||||
"$_tests/GpuSampleLocationsTest.cpp",
|
|
||||||
"$_tests/GradientTest.cpp",
|
"$_tests/GradientTest.cpp",
|
||||||
"$_tests/GrAllocatorTest.cpp",
|
"$_tests/GrAllocatorTest.cpp",
|
||||||
"$_tests/GrCCPRTest.cpp",
|
"$_tests/GrCCPRTest.cpp",
|
||||||
|
@ -135,7 +135,6 @@ private:
|
|||||||
|
|
||||||
int fSampleCnt;
|
int fSampleCnt;
|
||||||
GrStencilAttachment* fStencilAttachment;
|
GrStencilAttachment* fStencilAttachment;
|
||||||
uint8_t fMultisampleSpecsID;
|
|
||||||
GrRenderTargetFlags fFlags;
|
GrRenderTargetFlags fFlags;
|
||||||
|
|
||||||
SkIRect fResolveRect;
|
SkIRect fResolveRect;
|
||||||
|
@ -78,8 +78,6 @@ void GrFragmentProcessor::markPendingExecution() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child) {
|
int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child) {
|
||||||
this->combineRequiredFeatures(*child);
|
|
||||||
|
|
||||||
if (child->usesLocalCoords()) {
|
if (child->usesLocalCoords()) {
|
||||||
fFlags |= kUsesLocalCoords_Flag;
|
fFlags |= kUsesLocalCoords_Flag;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ GrGpu::GrGpu(GrContext* context)
|
|||||||
: fResetTimestamp(kExpiredTimestamp+1)
|
: fResetTimestamp(kExpiredTimestamp+1)
|
||||||
, fResetBits(kAll_GrBackendState)
|
, fResetBits(kAll_GrBackendState)
|
||||||
, fContext(context) {
|
, fContext(context) {
|
||||||
fMultisampleSpecs.emplace_back(0, 0, nullptr); // Index 0 is an invalid unique id.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGpu::~GrGpu() {}
|
GrGpu::~GrGpu() {}
|
||||||
@ -451,65 +450,6 @@ void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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()) {
|
|
||||||
return a.count() < b.count();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < a.count(); ++i) {
|
|
||||||
// This doesn't have geometric meaning. We just need to define an ordering for std::map.
|
|
||||||
if (a[i].x() != b[i].x()) {
|
|
||||||
return a[i].x() < b[i].x();
|
|
||||||
}
|
|
||||||
if (a[i].y() != b[i].y()) {
|
|
||||||
return a[i].y() < b[i].y();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false; // Equal.
|
|
||||||
}
|
|
||||||
|
|
||||||
GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores,
|
GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores,
|
||||||
GrBackendSemaphore backendSemaphores[]) {
|
GrBackendSemaphore backendSemaphores[]) {
|
||||||
GrResourceProvider* resourceProvider = fContext->contextPriv().resourceProvider();
|
GrResourceProvider* resourceProvider = fContext->contextPriv().resourceProvider();
|
||||||
|
@ -321,33 +321,6 @@ public:
|
|||||||
const SkIRect& srcRect,
|
const SkIRect& srcRect,
|
||||||
const SkIPoint& dstPoint);
|
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
|
// Creates a GrGpuRTCommandBuffer which GrOpLists send draw commands to instead of directly
|
||||||
// to the Gpu object.
|
// to the Gpu object.
|
||||||
virtual GrGpuRTCommandBuffer* createCommandBuffer(
|
virtual GrGpuRTCommandBuffer* createCommandBuffer(
|
||||||
@ -594,11 +567,6 @@ private:
|
|||||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||||
const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
|
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 onFinishFlush(bool insertedSemaphores) = 0;
|
||||||
|
|
||||||
virtual void onDumpJSON(SkJSONWriter*) const {}
|
virtual void onDumpJSON(SkJSONWriter*) const {}
|
||||||
@ -609,18 +577,10 @@ private:
|
|||||||
++fResetTimestamp;
|
++fResetTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SamplePatternComparator {
|
ResetTimestamp fResetTimestamp;
|
||||||
bool operator()(const SamplePattern&, const SamplePattern&) const;
|
uint32_t fResetBits;
|
||||||
};
|
|
||||||
|
|
||||||
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.
|
// The context owns us, not vice-versa, so this ptr is not ref'ed by Gpu.
|
||||||
GrContext* fContext;
|
GrContext* fContext;
|
||||||
|
|
||||||
friend class GrPathRendering;
|
friend class GrPathRendering;
|
||||||
typedef SkRefCnt INHERITED;
|
typedef SkRefCnt INHERITED;
|
||||||
|
@ -167,18 +167,6 @@ public:
|
|||||||
return str;
|
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 new(size_t size);
|
||||||
void operator delete(void* target);
|
void operator delete(void* target);
|
||||||
|
|
||||||
@ -195,31 +183,15 @@ public:
|
|||||||
ClassID classID() const { return fClassID; }
|
ClassID classID() const { return fClassID; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GrProcessor(ClassID classID)
|
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:
|
private:
|
||||||
GrProcessor(const GrProcessor&) = delete;
|
GrProcessor(const GrProcessor&) = delete;
|
||||||
GrProcessor& operator=(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. */
|
/** A GrProcessor with the ability to access textures, buffers, and image storages. */
|
||||||
class GrResourceIOProcessor : public GrProcessor {
|
class GrResourceIOProcessor : public GrProcessor {
|
||||||
public:
|
public:
|
||||||
|
@ -166,7 +166,6 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
|
|||||||
desc->key().reset();
|
desc->key().reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
GrProcessor::RequiredFeatures requiredFeatures = primProc.requiredFeatures();
|
|
||||||
|
|
||||||
for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
|
for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
|
||||||
const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
|
const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
|
||||||
@ -174,7 +173,6 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
|
|||||||
desc->key().reset();
|
desc->key().reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
requiredFeatures |= fp.requiredFeatures();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const GrXferProcessor& xp = pipeline.getXferProcessor();
|
const GrXferProcessor& xp = pipeline.getXferProcessor();
|
||||||
@ -189,7 +187,6 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
|
|||||||
desc->key().reset();
|
desc->key().reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
requiredFeatures |= xp.requiredFeatures();
|
|
||||||
|
|
||||||
// --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
|
// --------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
|
// Because header is a pointer into the dynamic array, we can't push any new data into the key
|
||||||
@ -198,21 +195,7 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
|
|||||||
|
|
||||||
// make sure any padding in the header is zeroed.
|
// make sure any padding in the header is zeroed.
|
||||||
memset(header, 0, kHeaderSize);
|
memset(header, 0, kHeaderSize);
|
||||||
|
header->fOutputSwizzle = shaderCaps.configOutputSwizzle(pipeline.proxy()->config()).asKey();
|
||||||
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();
|
header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
|
||||||
header->fColorFragmentProcessorCnt = pipeline.numColorFragmentProcessors();
|
header->fColorFragmentProcessorCnt = pipeline.numColorFragmentProcessors();
|
||||||
header->fCoverageFragmentProcessorCnt = pipeline.numCoverageFragmentProcessors();
|
header->fCoverageFragmentProcessorCnt = pipeline.numCoverageFragmentProcessors();
|
||||||
|
@ -100,18 +100,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct KeyHeader {
|
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).
|
// Set to uniquely idenitify any swizzling of the shader's output color(s).
|
||||||
uint8_t fOutputSwizzle;
|
uint8_t fOutputSwizzle;
|
||||||
uint8_t fColorFragmentProcessorCnt : 4;
|
uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required.
|
||||||
uint8_t fCoverageFragmentProcessorCnt : 4;
|
uint8_t fCoverageFragmentProcessorCnt;
|
||||||
// Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
|
// Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
|
||||||
uint8_t fSurfaceOriginKey : 2;
|
uint8_t fSurfaceOriginKey : 2;
|
||||||
uint8_t fSnapVerticesToPixelCenters : 1;
|
bool fSnapVerticesToPixelCenters : 1;
|
||||||
uint8_t fHasPointSize : 1;
|
bool fHasPointSize : 1;
|
||||||
uint8_t fPad : 4;
|
uint8_t fPad : 4;
|
||||||
};
|
};
|
||||||
GR_STATIC_ASSERT(sizeof(KeyHeader) == 4);
|
GR_STATIC_ASSERT(sizeof(KeyHeader) == 4);
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
|
|||||||
: INHERITED(gpu, desc)
|
: INHERITED(gpu, desc)
|
||||||
, fSampleCnt(desc.fSampleCnt)
|
, fSampleCnt(desc.fSampleCnt)
|
||||||
, fStencilAttachment(stencil)
|
, fStencilAttachment(stencil)
|
||||||
, fMultisampleSpecsID(0)
|
|
||||||
, fFlags(flags) {
|
, fFlags(flags) {
|
||||||
SkASSERT(desc.fFlags & kRenderTarget_GrSurfaceFlag);
|
SkASSERT(desc.fFlags & kRenderTarget_GrSurfaceFlag);
|
||||||
SkASSERT(!(fFlags & GrRenderTargetFlags::kMixedSampled) || fSampleCnt > 1);
|
SkASSERT(!(fFlags & GrRenderTargetFlags::kMixedSampled) || fSampleCnt > 1);
|
||||||
@ -93,17 +92,3 @@ int GrRenderTargetPriv::numStencilBits() const {
|
|||||||
SkASSERT(this->getStencilAttachment());
|
SkASSERT(this->getStencilAttachment());
|
||||||
return this->getStencilAttachment()->bits();
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -32,11 +32,6 @@ public:
|
|||||||
|
|
||||||
int numStencilBits() const;
|
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; }
|
GrRenderTargetFlags flags() const { return fRenderTarget->fFlags; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -4297,38 +4297,6 @@ bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin
|
|||||||
return true;
|
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->flushRenderTargetNoColorWrites(static_cast<GrGLRenderTarget*>(rt));
|
|
||||||
|
|
||||||
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) {
|
void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) {
|
||||||
SkASSERT(type);
|
SkASSERT(type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -263,9 +263,6 @@ private:
|
|||||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||||
const SkIRect& srcRect, const SkIPoint& dstPoint) override;
|
const SkIRect& srcRect, const SkIPoint& dstPoint) override;
|
||||||
|
|
||||||
void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
|
|
||||||
int* effectiveSampleCnt, SamplePattern*) override;
|
|
||||||
|
|
||||||
// binds texture unit in GL
|
// binds texture unit in GL
|
||||||
void setTextureUnit(int unitIdx);
|
void setTextureUnit(int unitIdx);
|
||||||
|
|
||||||
|
@ -17,18 +17,6 @@
|
|||||||
|
|
||||||
const char* GrGLSLFragmentShaderBuilder::kDstColorName = "_dstColor";
|
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) {
|
static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
|
||||||
SkASSERT(GrBlendEquationIsAdvanced(equation));
|
SkASSERT(GrBlendEquationIsAdvanced(equation));
|
||||||
|
|
||||||
@ -84,11 +72,9 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
|
|||||||
, fHasCustomColorOutput(false)
|
, fHasCustomColorOutput(false)
|
||||||
, fCustomColorOutputIndex(-1)
|
, fCustomColorOutputIndex(-1)
|
||||||
, fHasSecondaryOutput(false)
|
, fHasSecondaryOutput(false)
|
||||||
, fUsedSampleOffsetArrays(0)
|
|
||||||
, fForceHighPrecision(false) {
|
, fForceHighPrecision(false) {
|
||||||
fSubstageIndices.push_back(0);
|
fSubstageIndices.push_back(0);
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
|
|
||||||
fHasReadDstColor = false;
|
fHasReadDstColor = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -106,17 +92,6 @@ SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords)
|
|||||||
return coords2D;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GrGLSLFragmentShaderBuilder::dstColor() {
|
const char* GrGLSLFragmentShaderBuilder::dstColor() {
|
||||||
SkDEBUGCODE(fHasReadDstColor = true;)
|
SkDEBUGCODE(fHasReadDstColor = true;)
|
||||||
|
|
||||||
@ -218,33 +193,6 @@ GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
|
|||||||
|
|
||||||
void GrGLSLFragmentShaderBuilder::onFinalize() {
|
void GrGLSLFragmentShaderBuilder::onFinalize() {
|
||||||
fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
|
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() {
|
void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() {
|
||||||
|
@ -54,16 +54,6 @@ public:
|
|||||||
kLast_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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment procs with child procs should call these functions before/after calling emitCode
|
* Fragment procs with child procs should call these functions before/after calling emitCode
|
||||||
* on a child proc.
|
* on a child proc.
|
||||||
@ -112,7 +102,6 @@ public:
|
|||||||
virtual SkString ensureCoords2D(const GrShaderVar&) override;
|
virtual SkString ensureCoords2D(const GrShaderVar&) override;
|
||||||
|
|
||||||
// GrGLSLFPFragmentBuilder interface.
|
// GrGLSLFPFragmentBuilder interface.
|
||||||
void appendOffsetToSample(const char* sampleIdx, Coordinates) override;
|
|
||||||
const SkString& getMangleString() const override { return fMangleString; }
|
const SkString& getMangleString() const override { return fMangleString; }
|
||||||
void onBeforeChildProcEmitCode() override;
|
void onBeforeChildProcEmitCode() override;
|
||||||
void onAfterChildProcEmitCode() override;
|
void onAfterChildProcEmitCode() override;
|
||||||
@ -134,10 +123,8 @@ private:
|
|||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
// As GLSLProcessors emit code, there are some conditions we need to verify. We use the below
|
// 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.
|
// state to track this. The reset call is called per processor emitted.
|
||||||
GrProcessor::RequiredFeatures usedProcessorFeatures() const { return fUsedProcessorFeatures; }
|
|
||||||
bool hasReadDstColor() const { return fHasReadDstColor; }
|
bool hasReadDstColor() const { return fHasReadDstColor; }
|
||||||
void resetVerification() {
|
void resetVerification() {
|
||||||
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
|
|
||||||
fHasReadDstColor = false;
|
fHasReadDstColor = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -148,7 +135,6 @@ private:
|
|||||||
GrSurfaceOrigin getSurfaceOrigin() const;
|
GrSurfaceOrigin getSurfaceOrigin() const;
|
||||||
|
|
||||||
void onFinalize() override;
|
void onFinalize() override;
|
||||||
void defineSampleOffsetArray(const char* name, const SkMatrix&);
|
|
||||||
|
|
||||||
static const char* kDstColorName;
|
static const char* kDstColorName;
|
||||||
|
|
||||||
@ -176,13 +162,11 @@ private:
|
|||||||
bool fHasCustomColorOutput;
|
bool fHasCustomColorOutput;
|
||||||
int fCustomColorOutputIndex;
|
int fCustomColorOutputIndex;
|
||||||
bool fHasSecondaryOutput;
|
bool fHasSecondaryOutput;
|
||||||
uint8_t fUsedSampleOffsetArrays;
|
|
||||||
bool fForceHighPrecision;
|
bool fForceHighPrecision;
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
// some state to verify shaders and effects are consistent, this is reset between effects by
|
// some state to verify shaders and effects are consistent, this is reset between effects by
|
||||||
// the program creator
|
// the program creator
|
||||||
GrProcessor::RequiredFeatures fUsedProcessorFeatures;
|
|
||||||
bool fHasReadDstColor;
|
bool fHasReadDstColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -360,16 +360,13 @@ bool GrGLSLProgramBuilder::checkSamplerCounts() {
|
|||||||
|
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
|
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
|
||||||
SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
|
void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
|
||||||
SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
|
|
||||||
SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
|
SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
|
void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
|
||||||
SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -120,11 +120,6 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
|
|
||||||
int* effectiveSampleCnt, SamplePattern*) override {
|
|
||||||
*effectiveSampleCnt = rt->numStencilSamples();
|
|
||||||
}
|
|
||||||
|
|
||||||
void onResolveRenderTarget(GrRenderTarget* target) override { return; }
|
void onResolveRenderTarget(GrRenderTarget* target) override { return; }
|
||||||
|
|
||||||
void onFinishFlush(bool insertedSemaphores) override {}
|
void onFinishFlush(bool insertedSemaphores) override {}
|
||||||
|
@ -46,9 +46,6 @@ public:
|
|||||||
const SkIRect& srcRect,
|
const SkIRect& srcRect,
|
||||||
const SkIPoint& dstPoint) override { return false; }
|
const SkIPoint& dstPoint) override { return false; }
|
||||||
|
|
||||||
void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
|
|
||||||
int* effectiveSampleCnt, SamplePattern*) override {}
|
|
||||||
|
|
||||||
GrGpuRTCommandBuffer* createCommandBuffer(
|
GrGpuRTCommandBuffer* createCommandBuffer(
|
||||||
GrRenderTarget*, GrSurfaceOrigin,
|
GrRenderTarget*, GrSurfaceOrigin,
|
||||||
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
|
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
|
||||||
|
@ -1850,13 +1850,6 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
|||||||
return false;
|
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,
|
bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width,
|
||||||
int height, size_t rowBytes, GrPixelConfig dstConfig,
|
int height, size_t rowBytes, GrPixelConfig dstConfig,
|
||||||
DrawPreference* drawPreference,
|
DrawPreference* drawPreference,
|
||||||
|
@ -198,9 +198,6 @@ private:
|
|||||||
GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
|
GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
|
||||||
const SkIPoint& dstPoint) override;
|
const SkIPoint& dstPoint) override;
|
||||||
|
|
||||||
void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
|
|
||||||
int* effectiveSampleCnt, SamplePattern*) override;
|
|
||||||
|
|
||||||
void onFinishFlush(bool insertedSemaphores) override;
|
void onFinishFlush(bool insertedSemaphores) override;
|
||||||
|
|
||||||
// Ends and submits the current command buffer to the queue and then creates a new command
|
// Ends and submits the current command buffer to the queue and then creates a new command
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pick_random_sample_count(int testPatternSize, SkRandom* rand, const GrCaps* caps) {
|
|
||||||
GrAlwaysAssert(testPatternSize > 1 && SkIsPow2(testPatternSize));
|
|
||||||
int randSampCnt = rand->nextRangeU(1 + testPatternSize / 2, testPatternSize);
|
|
||||||
do {
|
|
||||||
int cnt = caps->getRenderTargetSampleCount(randSampCnt, kRGBA_8888_GrPixelConfig);
|
|
||||||
if (cnt) {
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
--randSampCnt;
|
|
||||||
} while (randSampCnt);
|
|
||||||
// This test assumes an MSAA kRGBA_8888 RTC can be created.
|
|
||||||
GrAlwaysAssert(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 patternSize = (int)kTestPatterns[i].size();
|
|
||||||
int randNumSamples = pick_random_sample_count(patternSize, &rand, ctx->caps());
|
|
||||||
bottomUps[i] = ctx->makeDeferredRenderTargetContext(
|
|
||||||
SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr, randNumSamples,
|
|
||||||
GrMipMapped::kNo, kBottomLeft_GrSurfaceOrigin);
|
|
||||||
randNumSamples = pick_random_sample_count(patternSize, &rand, ctx->caps());
|
|
||||||
topDowns[i] = ctx->makeDeferredRenderTargetContext(
|
|
||||||
SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr, randNumSamples,
|
|
||||||
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()->getRenderTargetSampleCount(2, kRGBA_8888_GrPixelConfig);
|
|
||||||
if (supportedSample < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
test_sampleLocations(reporter, testInterface.get(), ctx.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user