skia2/tests/BulkRectTest.cpp
Greg Daniel 47c20e81bc Pass swizzle into createProxy instead of inferring from GrPixelConfig.
This whole change is basically work that will all get reverted shortly
when GrSurfaceProxy no longer stores swizzle. But for now this helps
get rid of a use of pixel config.

Bug: skia:6718
Change-Id: If911360a8a9d2c52a58b5795386484634885b3f3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/265579
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
2020-01-21 20:58:32 +00:00

229 lines
9.9 KiB
C++

/*
* 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/core/SkBlendModePriv.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/ops/GrFillRectOp.h"
#include "src/gpu/ops/GrTextureOp.h"
#include "tests/Test.h"
static std::unique_ptr<GrRenderTargetContext> new_RTC(GrContext* context) {
return GrRenderTargetContext::Make(
context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact, {128, 128});
}
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);
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, GrColorType::kRGBA_8888);
return context->priv().proxyProvider()->createProxy(
format, desc, swizzle, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
SkBackingFit::kExact, SkBudgeted::kNo, GrProtected::kNo, GrInternalSurfaceFlags::kNone);
}
typedef GrQuadAAFlags (*PerQuadAAFunc)(int i);
typedef void (*BulkRectTest)(skiatest::Reporter* reporter, GrContext* context,
PerQuadAAFunc perQuadAA, GrAAType overallAA, SkBlendMode blendMode,
int requestedTotNumQuads, int expectedNumOps);
//-------------------------------------------------------------------------------------------------
static void bulk_fill_rect_create_test(skiatest::Reporter* reporter, GrContext* context,
PerQuadAAFunc perQuadAA, GrAAType overallAA,
SkBlendMode blendMode,
int requestedTotNumQuads, int expectedNumOps) {
std::unique_ptr<GrRenderTargetContext> rtc = new_RTC(context);
auto quads = new GrRenderTargetContext::QuadSetEntry[requestedTotNumQuads];
for (int i = 0; i < requestedTotNumQuads; ++i) {
quads[i].fRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
quads[i].fColor = SK_PMColor4fWHITE;
quads[i].fLocalMatrix = SkMatrix::I();
quads[i].fAAFlags = perQuadAA(i);
}
GrPaint paint;
paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
GrFillRectOp::AddFillRectOps(rtc.get(), GrNoClip(), context, std::move(paint), overallAA,
SkMatrix::I(), quads, requestedTotNumQuads);
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() == GrFillRectOp::ClassID());
REPORTER_ASSERT(reporter, tmp->isChainTail());
actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
}
REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
context->flush();
delete[] quads;
}
//-------------------------------------------------------------------------------------------------
static void bulk_texture_rect_create_test(skiatest::Reporter* reporter, GrContext* context,
PerQuadAAFunc perQuadAA, GrAAType overallAA,
SkBlendMode blendMode,
int requestedTotNumQuads, int expectedNumOps) {
std::unique_ptr<GrRenderTargetContext> rtc = new_RTC(context);
sk_sp<GrSurfaceProxy> proxyA = create_proxy(context);
sk_sp<GrSurfaceProxy> proxyB = create_proxy(context);
GrSurfaceProxyView proxyViewA(std::move(proxyA), kTopLeft_GrSurfaceOrigin, GrSwizzle::RGBA());
GrSurfaceProxyView proxyViewB(std::move(proxyB), kTopLeft_GrSurfaceOrigin, GrSwizzle::RGBA());
auto set = new GrRenderTargetContext::TextureSetEntry[requestedTotNumQuads];
for (int i = 0; i < requestedTotNumQuads; ++i) {
// Alternate between two proxies to prevent op merging if the batch API was forced to submit
// one op at a time (to work, this does require that all fDstRects overlap).
set[i].fProxyView = i % 2 == 0 ? proxyViewA : proxyViewB;
set[i].fSrcAlphaType = kPremul_SkAlphaType;
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 = perQuadAA(i);
}
GrTextureOp::AddTextureSetOps(rtc.get(), GrNoClip(), context, set, requestedTotNumQuads,
requestedTotNumQuads, // We alternate so proxyCnt == cnt
GrSamplerState::Filter::kNearest,
GrTextureOp::Saturate::kYes,
blendMode,
overallAA,
SkCanvas::kStrict_SrcRectConstraint,
SkMatrix::I(), nullptr);
GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
int actualNumOps = opsTask->numOpChains();
int actualTotNumQuads = 0;
if (blendMode != SkBlendMode::kSrcOver ||
!context->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
// In either of these two cases, GrTextureOp creates one op per quad instead. Since
// each entry alternates proxies but overlaps geometrically, this will prevent the ops
// from being merged back into fewer ops.
expectedNumOps = requestedTotNumQuads;
}
uint32_t expectedOpID = blendMode == SkBlendMode::kSrcOver ? GrTextureOp::ClassID()
: GrFillRectOp::ClassID();
for (int i = 0; i < actualNumOps; ++i) {
const GrOp* tmp = opsTask->getChain(i);
REPORTER_ASSERT(reporter, tmp->classID() == expectedOpID);
REPORTER_ASSERT(reporter, tmp->isChainTail());
actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
}
REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
context->flush();
delete[] set;
}
//-------------------------------------------------------------------------------------------------
static void run_test(GrContext* context, skiatest::Reporter* reporter, BulkRectTest test) {
// 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;
test(reporter, context, noAA, GrAAType::kNone, SkBlendMode::kSrcOver,
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;
test(reporter, context, noAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
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();
test(reporter, context, alternateAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
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;
test(reporter, context, runOfNonAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
}
// In this case we use a blend mode other than src-over, which hits the GrFillRectOp fallback
// code path for GrTextureOp. We pass in the expected results if batching was successful, to
// that bulk_fill_rect_create_test batches on all modes; bulk_texture_rect_create_test is
// responsible for revising its expectations.
{
auto fixedAA = [](int i) -> GrQuadAAFlags {
return GrQuadAAFlags::kAll;
};
static const int kNumExpectedOps = 2;
test(reporter, context, fixedAA, GrAAType::kCoverage, SkBlendMode::kSrcATop,
2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
}
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BulkFillRectTest, reporter, ctxInfo) {
run_test(ctxInfo.grContext(), reporter, bulk_fill_rect_create_test);
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BulkTextureRectTest, reporter, ctxInfo) {
run_test(ctxInfo.grContext(), reporter, bulk_texture_rect_create_test);
}