Enable wide color support in CCPR
Unlike other ops, always use half-float colors. The logic around the
Instance struct makes dynamically switching color size tricky.
CCPR stores color in a per-instance attribute though, so the cost of
always using FP16 is much lower.
Bug: skia:
Change-Id: I9c0c64940f74f915a18417a5830030558e065d28
Reviewed-on: https://skia-review.googlesource.com/c/182760
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index fe1365b..13b21d0 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -174,7 +174,6 @@
fShape = GrShape(path, GrStyle(hairlineStroke, nullptr));
fStrokeDevWidth = 1;
- // TODO4F: Preserve float colors
// fShapeConservativeIBounds already accounted for this possibility of inflating the stroke.
fColor = fColor * coverage;
}
@@ -350,9 +349,8 @@
#endif
op->recordInstance(fCacheEntry->cachedAtlas()->getOnFlushProxy(),
resources->nextPathInstanceIdx());
- // TODO4F: Preserve float colors
resources->appendDrawPathInstance().set(*fCacheEntry, fCachedMaskShift,
- fColor.toBytes_RGBA());
+ SkPMColor4f_toFP16(fColor));
return;
}
}
@@ -368,9 +366,8 @@
fMaskDevIBounds, fMatrix, fShape, fStrokeDevWidth, &devBounds, &devBounds45,
&devIBounds, &devToAtlasOffset)) {
op->recordInstance(atlas->textureProxy(), resources->nextPathInstanceIdx());
- // TODO4F: Preserve float colors
resources->appendDrawPathInstance().set(devBounds, devBounds45, devToAtlasOffset,
- fColor.toBytes_RGBA(), doEvenOddFill);
+ SkPMColor4f_toFP16(fColor), doEvenOddFill);
if (fDoCachePathMask) {
SkASSERT(fCacheEntry);
diff --git a/src/gpu/ccpr/GrCCPathCache.h b/src/gpu/ccpr/GrCCPathCache.h
index 5fa5d4d..688521b 100644
--- a/src/gpu/ccpr/GrCCPathCache.h
+++ b/src/gpu/ccpr/GrCCPathCache.h
@@ -268,7 +268,7 @@
friend class GrCCPathCache;
friend void GrCCPathProcessor::Instance::set(const GrCCPathCacheEntry&, const SkIVector&,
- GrColor, DoEvenOddFill); // To access data.
+ uint64_t color, DoEvenOddFill); // To access data.
public:
int testingOnly_peekOnFlushRefCnt() const;
@@ -360,7 +360,7 @@
}
inline void GrCCPathProcessor::Instance::set(const GrCCPathCacheEntry& entry,
- const SkIVector& shift, GrColor color,
+ const SkIVector& shift, uint64_t color,
DoEvenOddFill doEvenOddFill) {
float dx = (float)shift.fX, dy = (float)shift.fY;
this->set(entry.fDevBounds.makeOffset(dx, dy), MakeOffset45(entry.fDevBounds45, dx, dy),
diff --git a/src/gpu/ccpr/GrCCPathProcessor.h b/src/gpu/ccpr/GrCCPathProcessor.h
index bd544bb..2f54d67 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.h
+++ b/src/gpu/ccpr/GrCCPathProcessor.h
@@ -56,15 +56,15 @@
SkRect fDevBounds45; // Bounding box in "| 1 -1 | * devCoords" space.
// | 1 1 |
SkIVector fDevToAtlasOffset; // Translation from device space to location in atlas.
- GrColor fColor;
+ uint64_t fColor; // Color always stored as 4 x fp16
void set(const SkRect& devBounds, const SkRect& devBounds45,
- const SkIVector& devToAtlasOffset, GrColor, DoEvenOddFill = DoEvenOddFill::kNo);
- void set(const GrCCPathCacheEntry&, const SkIVector& shift, GrColor,
+ const SkIVector& devToAtlasOffset, uint64_t, DoEvenOddFill = DoEvenOddFill::kNo);
+ void set(const GrCCPathCacheEntry&, const SkIVector& shift, uint64_t,
DoEvenOddFill = DoEvenOddFill::kNo);
};
- GR_STATIC_ASSERT(4 * 11 == sizeof(Instance));
+ GR_STATIC_ASSERT(4 * 12 == sizeof(Instance));
static sk_sp<const GrBuffer> FindVertexBuffer(GrOnFlushResourceProvider*);
static sk_sp<const GrBuffer> FindIndexBuffer(GrOnFlushResourceProvider*);
@@ -102,7 +102,7 @@
{"devbounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
{"devbounds45", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
{"dev_to_atlas_offset", kInt2_GrVertexAttribType, kInt2_GrSLType},
- {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType}
+ {"color", kHalf4_GrVertexAttribType, kHalf4_GrSLType}
};
static constexpr Attribute kEdgeNormsAttrib = {"edge_norms", kFloat4_GrVertexAttribType,
kFloat4_GrSLType};
@@ -111,7 +111,7 @@
};
inline void GrCCPathProcessor::Instance::set(const SkRect& devBounds, const SkRect& devBounds45,
- const SkIVector& devToAtlasOffset, GrColor color,
+ const SkIVector& devToAtlasOffset, uint64_t color,
DoEvenOddFill doEvenOddFill) {
if (DoEvenOddFill::kYes == doEvenOddFill) {
// "right < left" indicates even-odd fill type.
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index e6cf8bb..5d4ca94 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -251,7 +251,11 @@
// Write the instance at the back of the array.
int currentInstanceIdx = fNextCopyInstanceIdx++;
- fPathInstanceData[currentInstanceIdx].set(entry, newAtlasOffset, GrColor_WHITE, evenOdd);
+ constexpr uint64_t kWhite = (((uint64_t) SK_Half1) << 0) |
+ (((uint64_t) SK_Half1) << 16) |
+ (((uint64_t) SK_Half1) << 32) |
+ (((uint64_t) SK_Half1) << 48);
+ fPathInstanceData[currentInstanceIdx].set(entry, newAtlasOffset, kWhite, evenOdd);
// Percolate the instance forward until it's contiguous with other instances that share the same
// proxy.
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index 901ca38..077b0ec 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -26,6 +26,7 @@
caps.isConfigRenderable(kAlpha_half_GrPixelConfig) &&
caps.isConfigTexturable(kAlpha_8_GrPixelConfig) &&
caps.isConfigRenderable(kAlpha_8_GrPixelConfig) &&
+ caps.halfFloatVertexAttributeSupport() &&
!caps.blacklistCoverageCounting();
}
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 19c0d1b..e207e15 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -502,7 +502,7 @@
// that these factories could simply return the input FP. However, that doesn't have quite
// the same effect as the returned compose FP will replace the FP's input with solid white and
// ignore the original input. This could be implemented as:
-// RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
+// RunInSeries(ConstColor(WHITE, kIgnoreInput), inputFP).
std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index c58b9bb..65aee42 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -17,6 +17,7 @@
GrMockCaps(const GrContextOptions& contextOptions, const GrMockOptions& options)
: INHERITED(contextOptions), fOptions(options) {
fInstanceAttribSupport = options.fInstanceAttribSupport;
+ fHalfFloatVertexAttributeSupport = options.fHalfFloatVertexAttributeSupport;
fMapBufferFlags = options.fMapBufferFlags;
fBufferMapThreshold = SK_MaxS32; // Overridable in GrContextOptions.
fMaxTextureSize = options.fMaxTextureSize;