8499e372ce
While I was fixing up Chrome's uses, I found some failures there that I did not see in Skia, and tracked them down to a few other places where we include SkColorSpace and it is not strictly necessary - SkCustomMesh.h - GrColorInfo.h - GrColorSpaceXform.h - SkColorSpaceXformSteps.h For these files (and their .cpp files), I added enforcement of include-what-you-use, and then fixed the myriad of places which were depending on these transitive includes. One change to help Chrome is the manual overloads of SkImage::MakeFromAdoptedTexture instead of using default parameters. This makes it so callers of that function do not need to include SkColorSpace if they were going to pass nullptr for it anyway. Bug: skia:13052 Change-Id: I16bf8ed5e258225d887f562f2c189623b1ca9c23 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/527056 Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Kevin Lubick <kjlubick@google.com>
261 lines
9.9 KiB
C++
261 lines
9.9 KiB
C++
/*
|
|
* Copyright 2017 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "include/core/SkTypes.h"
|
|
#include "tests/Test.h"
|
|
|
|
#include "include/core/SkColorSpace.h"
|
|
#include "include/gpu/GrDirectContext.h"
|
|
#include "include/gpu/GrRecordingContext.h"
|
|
#include "src/gpu/GrColor.h"
|
|
#include "src/gpu/GrDirectContextPriv.h"
|
|
#include "src/gpu/GrGeometryProcessor.h"
|
|
#include "src/gpu/GrImageInfo.h"
|
|
#include "src/gpu/GrMemoryPool.h"
|
|
#include "src/gpu/GrOpFlushState.h"
|
|
#include "src/gpu/GrOpsRenderPass.h"
|
|
#include "src/gpu/GrProgramInfo.h"
|
|
#include "src/gpu/GrRecordingContextPriv.h"
|
|
#include "src/gpu/GrResourceProvider.h"
|
|
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
|
#include "src/gpu/glsl/GrGLSLVarying.h"
|
|
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
|
|
#include "src/gpu/ops/GrDrawOp.h"
|
|
#include "src/gpu/v1/SurfaceDrawContext_v1.h"
|
|
|
|
/**
|
|
* This is a GPU-backend specific test for dynamic pipeline state. It draws boxes using dynamic
|
|
* scissor rectangles then reads back the result to verify a successful test.
|
|
*/
|
|
|
|
static constexpr int kScreenSize = 6;
|
|
static constexpr int kNumMeshes = 4;
|
|
static constexpr int kScreenSplitX = kScreenSize/2;
|
|
static constexpr int kScreenSplitY = kScreenSize/2;
|
|
|
|
static const SkIRect kDynamicScissors[kNumMeshes] = {
|
|
SkIRect::MakeLTRB(0, 0, kScreenSplitX, kScreenSplitY),
|
|
SkIRect::MakeLTRB(0, kScreenSplitY, kScreenSplitX, kScreenSize),
|
|
SkIRect::MakeLTRB(kScreenSplitX, 0, kScreenSize, kScreenSplitY),
|
|
SkIRect::MakeLTRB(kScreenSplitX, kScreenSplitY, kScreenSize, kScreenSize),
|
|
};
|
|
|
|
static const GrColor kMeshColors[kNumMeshes] {
|
|
GrColorPackRGBA(255, 0, 0, 255),
|
|
GrColorPackRGBA(0, 255, 0, 255),
|
|
GrColorPackRGBA(0, 0, 255, 255),
|
|
GrColorPackRGBA(0, 0, 0, 255)
|
|
};
|
|
|
|
struct Vertex {
|
|
float fX;
|
|
float fY;
|
|
GrColor fColor;
|
|
};
|
|
|
|
namespace {
|
|
class PipelineDynamicStateTestProcessor : public GrGeometryProcessor {
|
|
public:
|
|
static GrGeometryProcessor* Make(SkArenaAlloc* arena) {
|
|
return arena->make(
|
|
[&](void* ptr) { return new (ptr) PipelineDynamicStateTestProcessor(); });
|
|
}
|
|
|
|
const char* name() const override { return "GrPipelineDynamicStateTest Processor"; }
|
|
|
|
void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const final {}
|
|
|
|
std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final;
|
|
|
|
private:
|
|
PipelineDynamicStateTestProcessor() : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) {
|
|
this->setVertexAttributesWithImplicitOffsets(kAttributes, SK_ARRAY_COUNT(kAttributes));
|
|
}
|
|
|
|
const Attribute& inVertex() const { return kAttributes[0]; }
|
|
const Attribute& inColor() const { return kAttributes[1]; }
|
|
|
|
inline static constexpr Attribute kAttributes[] = {
|
|
{"vertex", kFloat2_GrVertexAttribType, SkSLType::kHalf2},
|
|
{"color", kUByte4_norm_GrVertexAttribType, SkSLType::kHalf4},
|
|
};
|
|
|
|
friend class GLSLPipelineDynamicStateTestProcessor;
|
|
using INHERITED = GrGeometryProcessor;
|
|
};
|
|
} // anonymous namespace
|
|
|
|
std::unique_ptr<GrGeometryProcessor::ProgramImpl>
|
|
PipelineDynamicStateTestProcessor::makeProgramImpl(const GrShaderCaps&) const {
|
|
class Impl : public GrGeometryProcessor::ProgramImpl {
|
|
public:
|
|
void setData(const GrGLSLProgramDataManager&,
|
|
const GrShaderCaps&,
|
|
const GrGeometryProcessor&) final {}
|
|
|
|
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
|
|
const PipelineDynamicStateTestProcessor& mp =
|
|
args.fGeomProc.cast<PipelineDynamicStateTestProcessor>();
|
|
GrGLSLVertexBuilder* v = args.fVertBuilder;
|
|
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
|
|
|
|
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
|
|
varyingHandler->emitAttributes(mp);
|
|
f->codeAppendf("half4 %s;", args.fOutputColor);
|
|
varyingHandler->addPassThroughAttribute(mp.inColor().asShaderVar(), args.fOutputColor);
|
|
|
|
v->codeAppendf("float2 vertex = %s;", mp.inVertex().name());
|
|
gpArgs->fPositionVar.set(SkSLType::kFloat2, "vertex");
|
|
f->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
|
|
}
|
|
};
|
|
return std::make_unique<Impl>();
|
|
}
|
|
|
|
namespace {
|
|
class GrPipelineDynamicStateTestOp : public GrDrawOp {
|
|
public:
|
|
DEFINE_OP_CLASS_ID
|
|
|
|
static GrOp::Owner Make(GrRecordingContext* context,
|
|
GrScissorTest scissorTest,
|
|
sk_sp<const GrBuffer> vbuff) {
|
|
return GrOp::Make<GrPipelineDynamicStateTestOp>(context, scissorTest, std::move(vbuff));
|
|
}
|
|
|
|
private:
|
|
friend class GrOp;
|
|
|
|
GrPipelineDynamicStateTestOp(GrScissorTest scissorTest, sk_sp<const GrBuffer> vbuff)
|
|
: INHERITED(ClassID())
|
|
, fScissorTest(scissorTest)
|
|
, fVertexBuffer(std::move(vbuff)) {
|
|
this->setBounds(SkRect::MakeIWH(kScreenSize, kScreenSize),
|
|
HasAABloat::kNo, IsHairline::kNo);
|
|
}
|
|
|
|
const char* name() const override { return "GrPipelineDynamicStateTestOp"; }
|
|
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
|
|
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
|
|
return GrProcessorSet::EmptySetAnalysis();
|
|
}
|
|
void onPrePrepare(GrRecordingContext*,
|
|
const GrSurfaceProxyView& writeView,
|
|
GrAppliedClip*,
|
|
const GrDstProxyView&,
|
|
GrXferBarrierFlags renderPassXferBarriers,
|
|
GrLoadOp colorLoadOp) override {}
|
|
void onPrepare(GrOpFlushState*) override {}
|
|
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
|
|
GrPipeline pipeline(fScissorTest, SkBlendMode::kSrc,
|
|
flushState->drawOpArgs().writeView().swizzle());
|
|
SkSTArray<kNumMeshes, GrSimpleMesh> meshes;
|
|
for (int i = 0; i < kNumMeshes; ++i) {
|
|
GrSimpleMesh& mesh = meshes.push_back();
|
|
mesh.set(fVertexBuffer, 4, 4 * i);
|
|
}
|
|
|
|
auto geomProc = PipelineDynamicStateTestProcessor::Make(flushState->allocator());
|
|
|
|
GrProgramInfo programInfo(flushState->caps(),
|
|
flushState->writeView(),
|
|
flushState->usesMSAASurface(),
|
|
&pipeline,
|
|
&GrUserStencilSettings::kUnused,
|
|
geomProc,
|
|
GrPrimitiveType::kTriangleStrip, 0,
|
|
flushState->renderPassBarriers(),
|
|
flushState->colorLoadOp());
|
|
|
|
flushState->bindPipeline(programInfo, SkRect::MakeIWH(kScreenSize, kScreenSize));
|
|
for (int i = 0; i < 4; ++i) {
|
|
if (fScissorTest == GrScissorTest::kEnabled) {
|
|
flushState->setScissorRect(kDynamicScissors[i]);
|
|
}
|
|
flushState->drawMesh(meshes[i]);
|
|
}
|
|
}
|
|
|
|
GrScissorTest fScissorTest;
|
|
const sk_sp<const GrBuffer> fVertexBuffer;
|
|
|
|
using INHERITED = GrDrawOp;
|
|
};
|
|
} // anonymous namespace
|
|
|
|
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrPipelineDynamicStateTest, reporter, ctxInfo) {
|
|
auto dContext = ctxInfo.directContext();
|
|
GrResourceProvider* rp = dContext->priv().resourceProvider();
|
|
|
|
auto sdc = skgpu::v1::SurfaceDrawContext::Make(
|
|
dContext, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
|
|
{kScreenSize, kScreenSize}, SkSurfaceProps());
|
|
if (!sdc) {
|
|
ERRORF(reporter, "could not create render target context.");
|
|
return;
|
|
}
|
|
|
|
constexpr float d = (float) kScreenSize;
|
|
Vertex vdata[kNumMeshes * 4] = {
|
|
{0, 0, kMeshColors[0]},
|
|
{0, d, kMeshColors[0]},
|
|
{d, 0, kMeshColors[0]},
|
|
{d, d, kMeshColors[0]},
|
|
|
|
{0, 0, kMeshColors[1]},
|
|
{0, d, kMeshColors[1]},
|
|
{d, 0, kMeshColors[1]},
|
|
{d, d, kMeshColors[1]},
|
|
|
|
{0, 0, kMeshColors[2]},
|
|
{0, d, kMeshColors[2]},
|
|
{d, 0, kMeshColors[2]},
|
|
{d, d, kMeshColors[2]},
|
|
|
|
{0, 0, kMeshColors[3]},
|
|
{0, d, kMeshColors[3]},
|
|
{d, 0, kMeshColors[3]},
|
|
{d, d, kMeshColors[3]}
|
|
};
|
|
|
|
sk_sp<const GrBuffer> vbuff(rp->createBuffer(sizeof(vdata), GrGpuBufferType::kVertex,
|
|
kDynamic_GrAccessPattern, vdata));
|
|
if (!vbuff) {
|
|
ERRORF(reporter, "vbuff is null.");
|
|
return;
|
|
}
|
|
|
|
uint32_t resultPx[kScreenSize * kScreenSize];
|
|
|
|
for (GrScissorTest scissorTest : {GrScissorTest::kEnabled, GrScissorTest::kDisabled}) {
|
|
sdc->clear(SkPMColor4f::FromBytes_RGBA(0xbaaaaaad));
|
|
sdc->addDrawOp(GrPipelineDynamicStateTestOp::Make(dContext, scissorTest, vbuff));
|
|
auto ii = SkImageInfo::Make(kScreenSize, kScreenSize,
|
|
kRGBA_8888_SkColorType, kPremul_SkAlphaType);
|
|
GrPixmap resultPM(ii, resultPx, kScreenSize*sizeof(uint32_t));
|
|
sdc->readPixels(dContext, resultPM, {0, 0});
|
|
for (int y = 0; y < kScreenSize; ++y) {
|
|
for (int x = 0; x < kScreenSize; ++x) {
|
|
int expectedColorIdx;
|
|
if (GrScissorTest::kEnabled == scissorTest) {
|
|
expectedColorIdx = (x < kScreenSplitX ? 0 : 2) + (y < kScreenSplitY ? 0 : 1);
|
|
} else {
|
|
expectedColorIdx = kNumMeshes - 1;
|
|
}
|
|
uint32_t expected = kMeshColors[expectedColorIdx];
|
|
uint32_t actual = resultPx[y * kScreenSize + x];
|
|
if (expected != actual) {
|
|
ERRORF(reporter, "[scissor=%s] pixel (%i,%i): got 0x%x expected 0x%x",
|
|
GrScissorTest::kEnabled == scissorTest ? "enabled" : "disabled", x, y,
|
|
actual, expected);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|