aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2018-07-30 14:36:53 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-30 19:06:48 +0000
commit3ebd354730ea9590bf233deccfc24982ffe48a98 (patch)
treef9cef509dc7ccb769332cbbf740bfdbcead6dac8
parenta78b6dcb82d2f6c940e9c0a6bc14853f846344d0 (diff)
For TextureOp + Alpha texture, xform paint color to dest color space
This is an unfortunate amount of plumbing for this, but benchmarks confirm that we're better off doing this work in the vertex shader (with a ubyte attribute) than using a float4 attribute. Change-Id: I358d330ee452ea0a89cdd725019c8df2686036a0 Reviewed-on: https://skia-review.googlesource.com/144351 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
-rw-r--r--gm/clockwise.cpp4
-rw-r--r--src/gpu/GrRenderTargetContext.cpp6
-rw-r--r--src/gpu/GrRenderTargetContext.h2
-rw-r--r--src/gpu/SkGpuDevice_drawTexture.cpp18
-rw-r--r--src/gpu/ops/GrTextureOp.cpp110
-rw-r--r--src/gpu/ops/GrTextureOp.h3
6 files changed, 95 insertions, 48 deletions
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp
index 0ca6e0a567..00bc47ecda 100644
--- a/gm/clockwise.cpp
+++ b/gm/clockwise.cpp
@@ -168,7 +168,7 @@ void ClockwiseGM::onDraw(SkCanvas* canvas) {
GrSamplerState::Filter::kNearest, 0xffffffff, {0,0,100,200},
{100,0,200,200}, GrAA::kNo,
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
- nullptr);
+ nullptr, nullptr);
}
// Draw the test to an off-screen, bottom-up render target.
@@ -183,7 +183,7 @@ void ClockwiseGM::onDraw(SkCanvas* canvas) {
GrSamplerState::Filter::kNearest, 0xffffffff, {0,0,100,200},
{200,0,300,200}, GrAA::kNo,
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
- nullptr);
+ nullptr, nullptr);
}
}
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 7d88bc4936..a67e19a9d9 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -764,7 +764,8 @@ void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy
const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
SkCanvas::SrcRectConstraint constraint,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> colorSpaceXform) {
+ sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
@@ -790,7 +791,8 @@ void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy
}
this->addDrawOp(clip, GrTextureOp::Make(fContext, std::move(proxy), filter, color,
clippedSrcRect, clippedDstRect, aaType, constraint,
- viewMatrix, std::move(colorSpaceXform)));
+ viewMatrix, std::move(textureColorSpaceXform),
+ std::move(paintColorSpaceXform)));
}
void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 565a2b8c08..4e31a1a45d 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -148,7 +148,7 @@ public:
void drawTexture(const GrClip& clip, sk_sp<GrTextureProxy>, GrSamplerState::Filter, GrColor,
const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform>);
+ sk_sp<GrColorSpaceXform> texXform, sk_sp<GrColorSpaceXform> colorXform);
/**
* Draw a roundrect using a paint.
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index af397cd431..9b2641ea83 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -99,7 +99,6 @@ static bool can_use_draw_texture(const SkPaint& paint) {
static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect* src,
const SkRect* dst, GrAA aa, SkCanvas::SrcRectConstraint constraint,
sk_sp<GrTextureProxy> proxy,
-
SkColorSpace* colorSpace, const GrClip& clip, GrRenderTargetContext* rtc) {
SkASSERT(!(SkToBool(src) && !SkToBool(dst)));
SkRect srcRect = src ? *src : SkRect::MakeWH(proxy->width(), proxy->height());
@@ -111,7 +110,7 @@ static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect
SkAssertResult(srcRect.intersect(SkRect::MakeIWH(proxy->width(), proxy->height())));
srcToDst.mapRect(&dstRect, srcRect);
}
- auto csxf = GrColorSpaceXform::Make(colorSpace, rtc->colorSpaceInfo().colorSpace());
+ auto textureXform = GrColorSpaceXform::Make(colorSpace, rtc->colorSpaceInfo().colorSpace());
GrSamplerState::Filter filter;
switch (paint.getFilterQuality()) {
case kNone_SkFilterQuality:
@@ -124,11 +123,18 @@ static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect
case kHigh_SkFilterQuality:
SK_ABORT("Quality level not allowed.");
}
- GrColor color = GrPixelConfigIsAlphaOnly(proxy->config())
- ? SkColorToPremulGrColor(paint.getColor())
- : SkColorAlphaToGrColor(paint.getColor());
+ GrColor color;
+ sk_sp<GrColorSpaceXform> paintColorXform = nullptr;
+ if (GrPixelConfigIsAlphaOnly(proxy->config())) {
+ // Leave the color unpremul if we're going to transform it in the vertex shader
+ paintColorXform = rtc->colorSpaceInfo().refColorSpaceXformFromSRGB();
+ color = paintColorXform ? SkColorToUnpremulGrColor(paint.getColor())
+ : SkColorToPremulGrColor(paint.getColor());
+ } else {
+ color = SkColorAlphaToGrColor(paint.getColor());
+ }
rtc->drawTexture(clip, std::move(proxy), filter, color, srcRect, dstRect, aa, constraint, ctm,
- std::move(csxf));
+ std::move(textureXform), std::move(paintColorXform));
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 99ecdf8101..516cee628f 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -105,7 +105,9 @@ public:
}
static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxies[], int proxyCnt,
- sk_sp<GrColorSpaceXform> csxf, bool coverageAA,
+ sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform,
+ bool coverageAA,
bool perspective, Domain domain,
const GrSamplerState::Filter filters[],
const GrShaderCaps& caps) {
@@ -115,7 +117,9 @@ public:
size_t size = sizeof(TextureGeometryProcessor) + sizeof(TextureSampler) * (samplerCnt - 1);
void* mem = GrGeometryProcessor::operator new(size);
return sk_sp<TextureGeometryProcessor>(
- new (mem) TextureGeometryProcessor(proxies, proxyCnt, samplerCnt, std::move(csxf),
+ new (mem) TextureGeometryProcessor(proxies, proxyCnt, samplerCnt,
+ std::move(textureColorSpaceXform),
+ std::move(paintColorSpaceXform),
coverageAA, perspective, domain, filters, caps));
}
@@ -129,7 +133,8 @@ public:
const char* name() const override { return "TextureGeometryProcessor"; }
void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
- b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
+ b->add32(GrColorSpaceXform::XformKey(fTextureColorSpaceXform.get()));
+ b->add32(GrColorSpaceXform::XformKey(fPaintColorSpaceXform.get()));
uint32_t x = this->usesCoverageEdgeAA() ? 0 : 1;
x |= kFloat3_GrVertexAttribType == fPositions.type() ? 0 : 2;
x |= fDomain.isInitialized() ? 4 : 0;
@@ -143,15 +148,20 @@ public:
FPCoordTransformIter&& transformIter) override {
const auto& textureGP = proc.cast<TextureGeometryProcessor>();
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
- fColorSpaceXformHelper.setData(pdman, textureGP.fColorSpaceXform.get());
+ fTextureColorSpaceXformHelper.setData(
+ pdman, textureGP.fTextureColorSpaceXform.get());
+ fPaintColorSpaceXformHelper.setData(pdman, textureGP.fPaintColorSpaceXform.get());
}
private:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
using Interpolation = GrGLSLVaryingHandler::Interpolation;
const auto& textureGP = args.fGP.cast<TextureGeometryProcessor>();
- fColorSpaceXformHelper.emitCode(
- args.fUniformHandler, textureGP.fColorSpaceXform.get());
+ fTextureColorSpaceXformHelper.emitCode(
+ args.fUniformHandler, textureGP.fTextureColorSpaceXform.get());
+ fPaintColorSpaceXformHelper.emitCode(
+ args.fUniformHandler, textureGP.fPaintColorSpaceXform.get(),
+ kVertex_GrShaderFlag);
if (kFloat2_GrVertexAttribType == textureGP.fPositions.type()) {
args.fVaryingHandler->setNoPerspective();
}
@@ -163,8 +173,20 @@ public:
args.fUniformHandler,
textureGP.fTextureCoords.asShaderVar(),
args.fFPCoordTransformHandler);
- args.fVaryingHandler->addPassThroughAttribute(
- textureGP.fColors, args.fOutputColor, Interpolation::kCanBeFlat);
+ if (fPaintColorSpaceXformHelper.isNoop()) {
+ args.fVaryingHandler->addPassThroughAttribute(
+ textureGP.fColors, args.fOutputColor, Interpolation::kCanBeFlat);
+ } else {
+ GrGLSLVarying varying(kHalf4_GrSLType);
+ args.fVaryingHandler->addVarying("color", &varying);
+ args.fVertBuilder->codeAppend("half4 color = ");
+ args.fVertBuilder->appendColorGamutXform(textureGP.fColors.name(),
+ &fPaintColorSpaceXformHelper);
+ args.fVertBuilder->codeAppend(";");
+ args.fVertBuilder->codeAppendf("%s = half4(color.rgb * color.a, color.a);",
+ varying.vsOut());
+ args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
+ }
args.fFragBuilder->codeAppend("float2 texCoord;");
args.fVaryingHandler->addPassThroughAttribute(textureGP.fTextureCoords, "texCoord");
if (textureGP.fDomain.isInitialized()) {
@@ -185,21 +207,17 @@ public:
args.fFragBuilder->codeAppend("switch (texIdx) {");
for (int i = 0; i < textureGP.numTextureSamplers(); ++i) {
args.fFragBuilder->codeAppendf("case %d: %s = ", i, args.fOutputColor);
- args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
- args.fTexSamplers[i],
- "texCoord",
- kFloat2_GrSLType,
- &fColorSpaceXformHelper);
+ args.fFragBuilder->appendTextureLookupAndModulate(
+ args.fOutputColor, args.fTexSamplers[i], "texCoord",
+ kFloat2_GrSLType, &fTextureColorSpaceXformHelper);
args.fFragBuilder->codeAppend("; break;");
}
args.fFragBuilder->codeAppend("}");
} else {
args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor);
- args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
- args.fTexSamplers[0],
- "texCoord",
- kFloat2_GrSLType,
- &fColorSpaceXformHelper);
+ args.fFragBuilder->appendTextureLookupAndModulate(
+ args.fOutputColor, args.fTexSamplers[0], "texCoord",
+ kFloat2_GrSLType, &fTextureColorSpaceXformHelper);
}
args.fFragBuilder->codeAppend(";");
if (textureGP.usesCoverageEdgeAA()) {
@@ -244,7 +262,8 @@ public:
args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
}
}
- GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
+ GrGLSLColorSpaceXformHelper fTextureColorSpaceXformHelper;
+ GrGLSLColorSpaceXformHelper fPaintColorSpaceXformHelper;
};
return new GLSLProcessor;
}
@@ -268,10 +287,13 @@ private:
}
TextureGeometryProcessor(sk_sp<GrTextureProxy> proxies[], int proxyCnt, int samplerCnt,
- sk_sp<GrColorSpaceXform> csxf, bool coverageAA, bool perspective,
- Domain domain, const GrSamplerState::Filter filters[],
- const GrShaderCaps& caps)
- : INHERITED(kTextureGeometryProcessor_ClassID), fColorSpaceXform(std::move(csxf)) {
+ sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform,
+ bool coverageAA, bool perspective, Domain domain,
+ const GrSamplerState::Filter filters[], const GrShaderCaps& caps)
+ : INHERITED(kTextureGeometryProcessor_ClassID)
+ , fTextureColorSpaceXform(std::move(textureColorSpaceXform))
+ , fPaintColorSpaceXform(std::move(paintColorSpaceXform)) {
SkASSERT(proxyCnt > 0 && samplerCnt >= proxyCnt);
fSamplers[0].reset(std::move(proxies[0]), filters[0]);
this->addTextureSampler(&fSamplers[0]);
@@ -328,7 +350,8 @@ private:
Attribute fTextureIdx;
Attribute fDomain;
Attribute fAAEdges[4];
- sk_sp<GrColorSpaceXform> fColorSpaceXform;
+ sk_sp<GrColorSpaceXform> fTextureColorSpaceXform;
+ sk_sp<GrColorSpaceXform> fPaintColorSpaceXform;
TextureSampler fSamplers[1];
typedef GrGeometryProcessor INHERITED;
@@ -597,12 +620,14 @@ public:
GrAAType aaType,
SkCanvas::SrcRectConstraint constraint,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> csxf) {
+ sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform) {
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
return pool->allocate<TextureOp>(std::move(proxy), filter, color,
srcRect, dstRect, aaType, constraint,
- viewMatrix, std::move(csxf));
+ viewMatrix, std::move(textureColorSpaceXform),
+ std::move(paintColorSpaceXform));
}
~TextureOp() override {
@@ -685,9 +710,11 @@ __attribute__((no_sanitize("float-cast-overflow")))
TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, GrColor color,
const SkRect& srcRect, const SkRect& dstRect, GrAAType aaType,
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> csxf)
+ sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform)
: INHERITED(ClassID())
- , fColorSpaceXform(std::move(csxf))
+ , fTextureColorSpaceXform(std::move(textureColorSpaceXform))
+ , fPaintColorSpaceXform(std::move(paintColorSpaceXform))
, fProxy0(proxy.release())
, fFilter0(filter)
, fProxyCnt(1)
@@ -750,7 +777,8 @@ __attribute__((no_sanitize("float-cast-overflow")))
Domain domain = fDomain ? Domain::kYes : Domain::kNo;
bool coverageAA = GrAAType::kCoverage == this->aaType();
sk_sp<GrGeometryProcessor> gp = TextureGeometryProcessor::Make(
- proxiesSPs, fProxyCnt, std::move(fColorSpaceXform), coverageAA, fPerspective,
+ proxiesSPs, fProxyCnt, std::move(fTextureColorSpaceXform),
+ std::move(fPaintColorSpaceXform), coverageAA, fPerspective,
domain, filters, *target->caps().shaderCaps());
GrPipeline::InitArgs args;
args.fProxy = target->proxy();
@@ -842,7 +870,12 @@ __attribute__((no_sanitize("float-cast-overflow")))
bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
const auto* that = t->cast<TextureOp>();
const auto& shaderCaps = *caps.shaderCaps();
- if (!GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) {
+ if (!GrColorSpaceXform::Equals(fTextureColorSpaceXform.get(),
+ that->fTextureColorSpaceXform.get())) {
+ return false;
+ }
+ if (!GrColorSpaceXform::Equals(fPaintColorSpaceXform.get(),
+ that->fPaintColorSpaceXform.get())) {
return false;
}
if (this->aaType() != that->aaType()) {
@@ -850,7 +883,8 @@ __attribute__((no_sanitize("float-cast-overflow")))
}
// Because of an issue where GrColorSpaceXform adds the same function every time it is used
// in a texture lookup, we only allow multiple textures when there is no transform.
- if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) && !fColorSpaceXform &&
+ if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) &&
+ !fTextureColorSpaceXform &&
fMaxApproxDstPixelArea <= shaderCaps.disableImageMultitexturingDstRectAreaThreshold() &&
that->fMaxApproxDstPixelArea <=
shaderCaps.disableImageMultitexturingDstRectAreaThreshold()) {
@@ -999,7 +1033,8 @@ __attribute__((no_sanitize("float-cast-overflow")))
GrColor fColor;
};
SkSTArray<1, Draw, true> fDraws;
- sk_sp<GrColorSpaceXform> fColorSpaceXform;
+ sk_sp<GrColorSpaceXform> fTextureColorSpaceXform;
+ sk_sp<GrColorSpaceXform> fPaintColorSpaceXform;
// Initially we store a single proxy ptr and a single filter. If we grow to have more than
// one proxy we instead store pointers to dynamically allocated arrays of size kMaxTextures
// followed by kMaxTextures filters.
@@ -1035,9 +1070,11 @@ std::unique_ptr<GrDrawOp> Make(GrContext* context,
GrAAType aaType,
SkCanvas::SrcRectConstraint constraint,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> csxf) {
+ sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ sk_sp<GrColorSpaceXform> paintColorSpaceXform) {
return TextureOp::Make(context, std::move(proxy), filter, color, srcRect, dstRect, aaType,
- constraint, viewMatrix, std::move(csxf));
+ constraint, viewMatrix, std::move(textureColorSpaceXform),
+ std::move(paintColorSpaceXform));
}
} // namespace GrTextureOp
@@ -1078,7 +1115,8 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
filter = (GrSamplerState::Filter)random->nextULessThan(
static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1);
}
- auto csxf = GrTest::TestColorXform(random);
+ auto texXform = GrTest::TestColorXform(random);
+ auto paintXform = GrTest::TestColorXform(random);
GrAAType aaType = GrAAType::kNone;
if (random->nextBool()) {
aaType = (fsaaType == GrFSAAType::kUnifiedMSAA) ? GrAAType::kMSAA : GrAAType::kCoverage;
@@ -1086,7 +1124,7 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
auto constraint = random->nextBool() ? SkCanvas::kStrict_SrcRectConstraint
: SkCanvas::kFast_SrcRectConstraint;
return GrTextureOp::Make(context, std::move(proxy), filter, color, srcRect, rect, aaType,
- constraint, viewMatrix, std::move(csxf));
+ constraint, viewMatrix, std::move(texXform), std::move(paintXform));
}
#endif
diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h
index 7211b5edc2..96cbc70cb8 100644
--- a/src/gpu/ops/GrTextureOp.h
+++ b/src/gpu/ops/GrTextureOp.h
@@ -34,5 +34,6 @@ std::unique_ptr<GrDrawOp> Make(GrContext*,
GrAAType,
SkCanvas::SrcRectConstraint,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform>);
+ sk_sp<GrColorSpaceXform> textureXform,
+ sk_sp<GrColorSpaceXform> paintXform);
}