Respect the max indexBuffer limits in the bulk texture draw API
This is required before we can lower the max AA quad count (again). Bug: b/143572065 skia:9601 Change-Id: Id34123476ad49a57dc9ce7fe13f941c06f721b74 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252603 Commit-Queue: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
99e73fa8c1
commit
dd947ceb55
@ -24,6 +24,7 @@ tests_sources = [
|
||||
"$_tests/BlendTest.cpp",
|
||||
"$_tests/BlitMaskClip.cpp",
|
||||
"$_tests/BlurTest.cpp",
|
||||
"$_tests/BulkRectTest.cpp",
|
||||
"$_tests/CTest.cpp",
|
||||
"$_tests/CachedDataTest.cpp",
|
||||
"$_tests/CachedDecodingPixelRefTest.cpp",
|
||||
|
@ -106,6 +106,11 @@ public:
|
||||
SkDEBUGCODE(int numClips() const override { return fNumClips; })
|
||||
SkDEBUGCODE(void visitProxies_debugOnly(const VisitSurfaceProxyFunc&) const override;)
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
int numOpChains() const { return fOpChains.count(); }
|
||||
const GrOp* getChain(int index) const { return fOpChains[index].head(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool isNoOp() const {
|
||||
// TODO: GrLoadOp::kDiscard (i.e., storing a discard) should also be grounds for skipping
|
||||
|
@ -903,15 +903,15 @@ void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetE
|
||||
srcQuad, domain);
|
||||
}
|
||||
} else {
|
||||
// Can use a single op, avoiding GrPaint creation, and can batch across proxies
|
||||
// Create the minimum number of GrTextureOps needed to draw this set. Individual
|
||||
// GrTextureOps can rebind the texture between draws thus avoiding GrPaint (re)creation.
|
||||
AutoCheckFlush acf(this->drawingManager());
|
||||
GrAAType aaType = this->chooseAAType(aa);
|
||||
auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
|
||||
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
|
||||
: GrTextureOp::Saturate::kNo;
|
||||
auto op = GrTextureOp::MakeSet(fContext, set, cnt, filter, saturate, aaType, constraint,
|
||||
viewMatrix, std::move(texXform));
|
||||
this->addDrawOp(clip, std::move(op));
|
||||
GrTextureOp::CreateTextureSetOps(this, clip, fContext, set, cnt, filter, saturate, aaType,
|
||||
constraint, viewMatrix, std::move(texXform));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,6 +549,7 @@ private:
|
||||
friend class GrTessellatingPathRenderer; // for access to add[Mesh]DrawOp
|
||||
friend class GrCCPerFlushResources; // for access to addDrawOp
|
||||
friend class GrCoverageCountingPathRenderer; // for access to addDrawOp
|
||||
friend class GrTextureOp; // for access to addDrawOp
|
||||
// for a unit test
|
||||
friend void test_draw_op(GrContext*,
|
||||
GrRenderTargetContext*,
|
||||
|
@ -54,6 +54,11 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
// This is really only intended for GrTextureOp to override
|
||||
virtual int numQuads() const { return -1; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
typedef GrOp INHERITED;
|
||||
};
|
||||
|
@ -166,6 +166,18 @@ sk_sp<const GrBuffer> GetIndexBuffer(GrMeshDrawOp::Target* target,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
int QuadLimit(IndexBufferOption option) {
|
||||
switch (option) {
|
||||
case IndexBufferOption::kPictureFramed: return GrResourceProvider::MaxNumAAQuads();
|
||||
case IndexBufferOption::kIndexedRects: return GrResourceProvider::MaxNumNonAAQuads();
|
||||
case IndexBufferOption::kTriStrips: return SK_MaxS32; // not limited by an indexBuffer
|
||||
}
|
||||
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void ConfigureMesh(GrMesh* mesh, const VertexSpec& spec,
|
||||
int runningQuadCount, int quadsInDraw, int maxVerts,
|
||||
|
@ -151,6 +151,11 @@ namespace GrQuadPerEdgeAA {
|
||||
// It will, correctly, return nullptr if the indexBufferOption is kTriStrips.
|
||||
sk_sp<const GrBuffer> GetIndexBuffer(GrMeshDrawOp::Target*, IndexBufferOption);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// What is the maximum number of quads allowed for the specified indexBuffer option?
|
||||
int QuadLimit(IndexBufferOption);
|
||||
#endif
|
||||
|
||||
// This method will configure the vertex and index data of the provided 'mesh' to comply
|
||||
// with the indexing method specified in the vertexSpec. It is up to the calling code
|
||||
// to allocate and fill in the vertex data and acquire the correct indexBuffer if it is needed.
|
||||
|
@ -159,6 +159,7 @@ public:
|
||||
color, saturate, aaType, aaFlags, deviceQuad, localQuad,
|
||||
domain);
|
||||
}
|
||||
|
||||
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
const GrRenderTargetContext::TextureSetEntry set[],
|
||||
int cnt,
|
||||
@ -595,9 +596,11 @@ private:
|
||||
auto textureType = fViewCountPairs[0].fProxyView.asTextureProxy()->textureType();
|
||||
GrAAType aaType = this->aaType();
|
||||
|
||||
int quadCount = 0;
|
||||
for (const auto& op : ChainRange<TextureOp>(this)) {
|
||||
for (unsigned p = 0; p < op.fProxyCnt; ++p) {
|
||||
auto* proxy = op.fViewCountPairs[p].fProxyView.asTextureProxy();
|
||||
quadCount += op.fViewCountPairs[p].fQuadCnt;
|
||||
SkASSERT(proxy);
|
||||
SkASSERT(proxy->textureType() == textureType);
|
||||
SkASSERT(op.fViewCountPairs[p].fProxyView.swizzle() ==
|
||||
@ -612,9 +615,15 @@ private:
|
||||
SkASSERT(aaType == GrAAType::kMSAA && op.aaType() == GrAAType::kMSAA);
|
||||
}
|
||||
}
|
||||
|
||||
SkASSERT(quadCount == this->numChainedQuads());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
int numQuads() const final { return this->totNumQuads(); }
|
||||
#endif
|
||||
|
||||
void characterize(PrePreparedDesc* desc) const {
|
||||
GrQuad::Type quadType = GrQuad::Type::kAxisAligned;
|
||||
ColorType colorType = ColorType::kNone;
|
||||
@ -659,6 +668,8 @@ private:
|
||||
desc->fVertexSpec = VertexSpec(quadType, colorType, srcQuadType, /* hasLocal */ true,
|
||||
domain, overallAAType, /* alpha as coverage */ true,
|
||||
indexBufferOption);
|
||||
|
||||
SkASSERT(desc->fNumTotalQuads <= GrQuadPerEdgeAA::QuadLimit(indexBufferOption));
|
||||
}
|
||||
|
||||
int totNumQuads() const {
|
||||
@ -879,21 +890,25 @@ private:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace GrTextureOp {
|
||||
#if GR_TEST_UTILS
|
||||
uint32_t GrTextureOp::ClassID() {
|
||||
return TextureOp::ClassID();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
GrSurfaceProxyView proxyView,
|
||||
GrColorType srcColorType,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
const SkPMColor4f& color,
|
||||
Saturate saturate,
|
||||
SkBlendMode blendMode,
|
||||
GrAAType aaType,
|
||||
GrQuadAAFlags aaFlags,
|
||||
const GrQuad& deviceQuad,
|
||||
const GrQuad& localQuad,
|
||||
const SkRect* domain) {
|
||||
std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
|
||||
GrSurfaceProxyView proxyView,
|
||||
GrColorType srcColorType,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
const SkPMColor4f& color,
|
||||
Saturate saturate,
|
||||
SkBlendMode blendMode,
|
||||
GrAAType aaType,
|
||||
GrQuadAAFlags aaFlags,
|
||||
const GrQuad& deviceQuad,
|
||||
const GrQuad& localQuad,
|
||||
const SkRect* domain) {
|
||||
GrTextureProxy* proxy = proxyView.asTextureProxy();
|
||||
// Apply optimizations that are valid whether or not using GrTextureOp or GrFillRectOp
|
||||
if (domain && domain->contains(proxy->backingStoreBoundsRect())) {
|
||||
@ -938,20 +953,143 @@ std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
|
||||
const GrRenderTargetContext::TextureSetEntry set[],
|
||||
int cnt,
|
||||
GrSamplerState::Filter filter,
|
||||
Saturate saturate,
|
||||
GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
|
||||
return TextureOp::Make(context, set, cnt, filter, saturate, aaType, constraint, viewMatrix,
|
||||
std::move(textureColorSpaceXform));
|
||||
}
|
||||
// A helper class that assists in breaking up bulk API quad draws into manageable chunks.
|
||||
class GrTextureOp::BatchSizeLimiter {
|
||||
public:
|
||||
BatchSizeLimiter(GrRenderTargetContext* rtc,
|
||||
const GrClip& clip,
|
||||
GrRecordingContext* context,
|
||||
int numEntries,
|
||||
GrSamplerState::Filter filter,
|
||||
GrTextureOp::Saturate saturate,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform)
|
||||
: fRTC(rtc)
|
||||
, fClip(clip)
|
||||
, fContext(context)
|
||||
, fFilter(filter)
|
||||
, fSaturate(saturate)
|
||||
, fConstraint(constraint)
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fTextureColorSpaceXform(textureColorSpaceXform)
|
||||
, fNumLeft(numEntries) {
|
||||
}
|
||||
|
||||
} // namespace GrTextureOp
|
||||
void createOp(const GrRenderTargetContext::TextureSetEntry set[],
|
||||
int clumpSize,
|
||||
GrAAType aaType) {
|
||||
std::unique_ptr<GrDrawOp> op = TextureOp::Make(fContext, &set[fNumClumped], clumpSize,
|
||||
fFilter, fSaturate, aaType,
|
||||
fConstraint, fViewMatrix,
|
||||
fTextureColorSpaceXform);
|
||||
fRTC->addDrawOp(fClip, std::move(op));
|
||||
|
||||
fNumLeft -= clumpSize;
|
||||
fNumClumped += clumpSize;
|
||||
}
|
||||
|
||||
int numLeft() const { return fNumLeft; }
|
||||
int baseIndex() const { return fNumClumped; }
|
||||
|
||||
private:
|
||||
GrRenderTargetContext* fRTC;
|
||||
const GrClip& fClip;
|
||||
GrRecordingContext* fContext;
|
||||
GrSamplerState::Filter fFilter;
|
||||
GrTextureOp::Saturate fSaturate;
|
||||
SkCanvas::SrcRectConstraint fConstraint;
|
||||
const SkMatrix& fViewMatrix;
|
||||
sk_sp<GrColorSpaceXform> fTextureColorSpaceXform;
|
||||
|
||||
int fNumLeft;
|
||||
int fNumClumped = 0; // also the offset for the start of the next clump
|
||||
};
|
||||
|
||||
// Greedily clump quad draws together until the index buffer limit is exceeded.
|
||||
void GrTextureOp::CreateTextureSetOps(GrRenderTargetContext* rtc,
|
||||
const GrClip& clip,
|
||||
GrRecordingContext* context,
|
||||
const GrRenderTargetContext::TextureSetEntry set[],
|
||||
int cnt,
|
||||
GrSamplerState::Filter filter,
|
||||
Saturate saturate,
|
||||
GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
|
||||
|
||||
// First check if we can always just make a single op and avoid the extra iteration
|
||||
// needed to clump things together.
|
||||
if (cnt <= SkTMin(GrResourceProvider::MaxNumNonAAQuads(),
|
||||
GrResourceProvider::MaxNumAAQuads())) {
|
||||
auto op = TextureOp::Make(context, set, cnt, filter, saturate, aaType,
|
||||
constraint, viewMatrix, std::move(textureColorSpaceXform));
|
||||
rtc->addDrawOp(clip, std::move(op));
|
||||
return;
|
||||
}
|
||||
|
||||
BatchSizeLimiter state(rtc, clip, context, cnt, filter, saturate, constraint, viewMatrix,
|
||||
std::move(textureColorSpaceXform));
|
||||
|
||||
// kNone and kMSAA never get altered
|
||||
if (aaType == GrAAType::kNone || aaType == GrAAType::kMSAA) {
|
||||
// Clump these into series of MaxNumNonAAQuads-sized GrTextureOps
|
||||
while (state.numLeft() > 0) {
|
||||
int clumpSize = SkTMin(state.numLeft(), GrResourceProvider::MaxNumNonAAQuads());
|
||||
|
||||
state.createOp(set, clumpSize, aaType);
|
||||
}
|
||||
} else {
|
||||
// kCoverage can be downgraded to kNone. Note that the following is conservative. kCoverage
|
||||
// can also get downgraded to kNone if all the quads are on integer coordinates and
|
||||
// axis-aligned.
|
||||
SkASSERT(aaType == GrAAType::kCoverage);
|
||||
|
||||
while (state.numLeft() > 0) {
|
||||
GrAAType runningAA = GrAAType::kNone;
|
||||
bool clumped = false;
|
||||
|
||||
for (int i = 0; i < state.numLeft(); ++i) {
|
||||
int absIndex = state.baseIndex() + i;
|
||||
|
||||
if (set[absIndex].fAAFlags != GrQuadAAFlags::kNone) {
|
||||
|
||||
if (i >= GrResourceProvider::MaxNumAAQuads()) {
|
||||
// Here we either need to boost the AA type to kCoverage, but doing so with
|
||||
// all the accumulated quads would overflow, or we have a set of AA quads
|
||||
// that has just gotten too large. In either case, calve off the existing
|
||||
// quads as their own TextureOp.
|
||||
state.createOp(
|
||||
set,
|
||||
runningAA == GrAAType::kNone ? i : GrResourceProvider::MaxNumAAQuads(),
|
||||
runningAA); // maybe downgrading AA here
|
||||
clumped = true;
|
||||
break;
|
||||
}
|
||||
|
||||
runningAA = GrAAType::kCoverage;
|
||||
} else if (runningAA == GrAAType::kNone) {
|
||||
|
||||
if (i >= GrResourceProvider::MaxNumNonAAQuads()) {
|
||||
// Here we've found a consistent batch of non-AA quads that has gotten too
|
||||
// large. Calve it off as its own GrTextureOp.
|
||||
state.createOp(set, GrResourceProvider::MaxNumNonAAQuads(),
|
||||
GrAAType::kNone); // definitely downgrading AA here
|
||||
clumped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!clumped) {
|
||||
// We ran through the above loop w/o hitting a limit. Spit out this last clump of
|
||||
// quads and call it a day.
|
||||
state.createOp(set, state.numLeft(), runningAA); // maybe downgrading AA here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
#include "include/private/GrRecordingContext.h"
|
||||
|
@ -20,49 +20,59 @@ class GrTextureProxy;
|
||||
struct SkRect;
|
||||
class SkMatrix;
|
||||
|
||||
namespace GrTextureOp {
|
||||
class GrTextureOp {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Controls whether saturate() is called after the texture is color-converted to ensure all
|
||||
* color values are in 0..1 range.
|
||||
*/
|
||||
enum class Saturate : bool { kNo = false, kYes = true };
|
||||
/**
|
||||
* Controls whether saturate() is called after the texture is color-converted to ensure all
|
||||
* color values are in 0..1 range.
|
||||
*/
|
||||
enum class Saturate : bool { kNo = false, kYes = true };
|
||||
|
||||
/**
|
||||
* Creates an op that draws a sub-quadrilateral of a texture. The passed color is modulated by the
|
||||
* texture's color. 'deviceQuad' specifies the device-space coordinates to draw, using 'localQuad'
|
||||
* to map into the proxy's texture space. If non-null, 'domain' represents the boundary for the
|
||||
* strict src rect constraint. If GrAAType is kCoverage then AA is applied to the edges
|
||||
* indicated by GrQuadAAFlags. Otherwise, GrQuadAAFlags is ignored.
|
||||
*
|
||||
* This is functionally very similar to GrFillRectOp::Make, except that the GrPaint has been
|
||||
* deconstructed into the texture, filter, modulating color, and blend mode. When blend mode is
|
||||
* src over, this will return a GrFillRectOp with a paint that samples the proxy.
|
||||
*/
|
||||
std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
|
||||
GrSurfaceProxyView,
|
||||
GrColorType srcColorType,
|
||||
sk_sp<GrColorSpaceXform>,
|
||||
GrSamplerState::Filter,
|
||||
const SkPMColor4f&,
|
||||
Saturate,
|
||||
SkBlendMode,
|
||||
GrAAType,
|
||||
GrQuadAAFlags,
|
||||
const GrQuad& deviceQuad,
|
||||
const GrQuad& localQuad,
|
||||
const SkRect* domain = nullptr);
|
||||
/**
|
||||
* Creates an op that draws a sub-quadrilateral of a texture. The passed color is modulated by
|
||||
* the texture's color. 'deviceQuad' specifies the device-space coordinates to draw, using
|
||||
* 'localQuad' to map into the proxy's texture space. If non-null, 'domain' represents the
|
||||
* boundary for the strict src rect constraint. If GrAAType is kCoverage then AA is applied to
|
||||
* the edges indicated by GrQuadAAFlags. Otherwise, GrQuadAAFlags is ignored.
|
||||
*
|
||||
* This is functionally very similar to GrFillRectOp::Make, except that the GrPaint has been
|
||||
* deconstructed into the texture, filter, modulating color, and blend mode. When blend mode is
|
||||
* src over, this will return a GrFillRectOp with a paint that samples the proxy.
|
||||
*/
|
||||
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
|
||||
GrSurfaceProxyView,
|
||||
GrColorType srcColorType,
|
||||
sk_sp<GrColorSpaceXform>,
|
||||
GrSamplerState::Filter,
|
||||
const SkPMColor4f&,
|
||||
Saturate,
|
||||
SkBlendMode,
|
||||
GrAAType,
|
||||
GrQuadAAFlags,
|
||||
const GrQuad& deviceQuad,
|
||||
const GrQuad& localQuad,
|
||||
const SkRect* domain = nullptr);
|
||||
|
||||
// Unlike the single-proxy factory, this only supports src-over blending.
|
||||
std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext*,
|
||||
const GrRenderTargetContext::TextureSetEntry[],
|
||||
int cnt,
|
||||
GrSamplerState::Filter,
|
||||
Saturate,
|
||||
GrAAType,
|
||||
SkCanvas::SrcRectConstraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureXform);
|
||||
// Unlike the single-proxy factory, this only supports src-over blending.
|
||||
static void CreateTextureSetOps(GrRenderTargetContext*,
|
||||
const GrClip& clip,
|
||||
GrRecordingContext*,
|
||||
const GrRenderTargetContext::TextureSetEntry[],
|
||||
int cnt,
|
||||
GrSamplerState::Filter,
|
||||
Saturate,
|
||||
GrAAType,
|
||||
SkCanvas::SrcRectConstraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureXform);
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
static uint32_t ClassID();
|
||||
#endif
|
||||
|
||||
private:
|
||||
class BatchSizeLimiter;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // GrTextureOp_DEFINED
|
||||
|
147
tests/BulkRectTest.cpp
Normal file
147
tests/BulkRectTest.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/GrClip.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrMemoryPool.h"
|
||||
#include "src/gpu/GrRenderTargetContext.h"
|
||||
#include "src/gpu/ops/GrTextureOp.h"
|
||||
#include "tests/Test.h"
|
||||
|
||||
static std::unique_ptr<GrRenderTargetContext> new_RTC(GrContext* context) {
|
||||
return context->priv().makeDeferredRenderTargetContext(SkBackingFit::kExact, 128, 128,
|
||||
GrColorType::kRGBA_8888, nullptr);
|
||||
}
|
||||
|
||||
sk_sp<GrSurfaceProxy> create_proxy(GrContext* context) {
|
||||
GrSurfaceDesc desc;
|
||||
desc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
desc.fWidth = 128;
|
||||
desc.fHeight = 128;
|
||||
|
||||
const GrBackendFormat format = context->priv().caps()->getDefaultBackendFormat(
|
||||
GrColorType::kRGBA_8888,
|
||||
GrRenderable::kYes);
|
||||
|
||||
return context->priv().proxyProvider()->createProxy(
|
||||
format, desc, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
|
||||
SkBackingFit::kExact, SkBudgeted::kNo, GrProtected::kNo, GrInternalSurfaceFlags::kNone);
|
||||
}
|
||||
|
||||
typedef GrQuadAAFlags (*GimmeSomeAAFunc)(int i);
|
||||
|
||||
static void bulk_rect_create_test(skiatest::Reporter* reporter, GrContext* context,
|
||||
GimmeSomeAAFunc gimmeSomeAA, GrAAType overallAA,
|
||||
int requestedTotNumQuads, int expectedNumOps) {
|
||||
|
||||
std::unique_ptr<GrRenderTargetContext> rtc = new_RTC(context);
|
||||
|
||||
sk_sp<GrSurfaceProxy> proxy = create_proxy(context);
|
||||
|
||||
GrSurfaceProxyView proxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, GrSwizzle::RGBA());
|
||||
|
||||
auto set = new GrRenderTargetContext::TextureSetEntry[requestedTotNumQuads];
|
||||
|
||||
for (int i = 0; i < requestedTotNumQuads; ++i) {
|
||||
set[i].fProxyView = proxyView;
|
||||
set[i].fSrcColorType = GrColorType::kRGBA_8888;
|
||||
set[i].fSrcRect = SkRect::MakeWH(100.0f, 100.0f);
|
||||
set[i].fDstRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
|
||||
set[i].fDstClipQuad = nullptr;
|
||||
set[i].fPreViewMatrix = nullptr;
|
||||
set[i].fAlpha = 1.0f;
|
||||
set[i].fAAFlags = gimmeSomeAA(i);
|
||||
}
|
||||
|
||||
GrTextureOp::CreateTextureSetOps(rtc.get(), GrNoClip(), context, set, requestedTotNumQuads,
|
||||
GrSamplerState::Filter::kNearest,
|
||||
GrTextureOp::Saturate::kYes,
|
||||
overallAA,
|
||||
SkCanvas::kStrict_SrcRectConstraint,
|
||||
SkMatrix::I(), nullptr);
|
||||
|
||||
GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
|
||||
int actualNumOps = opsTask->numOpChains();
|
||||
|
||||
int actualTotNumQuads = 0;
|
||||
|
||||
for (int i = 0; i < actualNumOps; ++i) {
|
||||
const GrOp* tmp = opsTask->getChain(i);
|
||||
REPORTER_ASSERT(reporter, tmp->classID() == GrTextureOp::ClassID());
|
||||
REPORTER_ASSERT(reporter, tmp->isChainTail());
|
||||
actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
|
||||
}
|
||||
|
||||
REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
|
||||
REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
|
||||
|
||||
context->flush();
|
||||
|
||||
delete[] set;
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BulkRect, reporter, ctxInfo) {
|
||||
GrContext* context = ctxInfo.grContext();
|
||||
|
||||
if (!context->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the simple case where there is no AA at all. We expect 2 non-AA clumps of quads.
|
||||
{
|
||||
auto noAA = [](int i) -> GrQuadAAFlags {
|
||||
return GrQuadAAFlags::kNone;
|
||||
};
|
||||
|
||||
static const int kNumExpectedOps = 2;
|
||||
|
||||
bulk_rect_create_test(reporter, context, noAA, GrAAType::kNone,
|
||||
2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
|
||||
}
|
||||
|
||||
// This is the same as the above case except the overall AA is kCoverage. However, since
|
||||
// the per-quad AA is still none, all the quads should be downgraded to non-AA.
|
||||
{
|
||||
auto noAA = [](int i) -> GrQuadAAFlags {
|
||||
return GrQuadAAFlags::kNone;
|
||||
};
|
||||
|
||||
static const int kNumExpectedOps = 2;
|
||||
|
||||
bulk_rect_create_test(reporter, context, noAA, GrAAType::kCoverage,
|
||||
2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
|
||||
}
|
||||
|
||||
// This case has an overall AA of kCoverage but the per-quad AA alternates.
|
||||
// We should end up with several aa-sized clumps
|
||||
{
|
||||
auto alternateAA = [](int i) -> GrQuadAAFlags {
|
||||
return (i % 2) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
|
||||
};
|
||||
|
||||
int numExpectedOps = 2*GrResourceProvider::MaxNumNonAAQuads() /
|
||||
GrResourceProvider::MaxNumAAQuads();
|
||||
|
||||
bulk_rect_create_test(reporter, context, alternateAA, GrAAType::kCoverage,
|
||||
2*GrResourceProvider::MaxNumNonAAQuads(), numExpectedOps);
|
||||
}
|
||||
|
||||
// In this case we have a run of MaxNumAAQuads non-AA quads and then AA quads. This
|
||||
// exercises the case where we have a clump of quads that can't be upgraded to AA bc of
|
||||
// its size. We expect one clump of non-AA quads followed by one clump of AA quads.
|
||||
{
|
||||
auto runOfNonAA = [](int i) -> GrQuadAAFlags {
|
||||
return (i < GrResourceProvider::MaxNumAAQuads()) ? GrQuadAAFlags::kNone
|
||||
: GrQuadAAFlags::kAll;
|
||||
};
|
||||
|
||||
static const int kNumExpectedOps = 2;
|
||||
|
||||
bulk_rect_create_test(reporter, context, runOfNonAA, GrAAType::kCoverage,
|
||||
2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user