aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2017-11-20 12:36:16 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-20 18:07:08 +0000
commit999ec57291dc7cf1d8e3a745627670e6cadc1c12 (patch)
tree78b34ac300515da3103c730345d4f0390959fb97
parent40dc8a71f5d55dd7ed4e64c883664efae6da70ca (diff)
Use int when possible to calculate atlas indices in shaders.
On certain iOS devices half has a mantissa of only 10 bits, which is not enough to perform the floating point trickery to get the lower bits out of the "texture coordinates". Instead we use int if available, and float if not available. Also re-enables multitexturing for iOS and adds a sample which stresses the issue. Bug: skia:7285 Change-Id: I365532c7cbbcca7c7753af209bef46e05be49e11 Reviewed-on: https://skia-review.googlesource.com/71181 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
-rw-r--r--gn/samples.gni1
-rw-r--r--samplecode/SampleFlutterAnimate.cpp107
-rw-r--r--src/gpu/GrContext.cpp20
-rw-r--r--src/gpu/effects/GrAtlasedShaderHelpers.h20
-rw-r--r--src/gpu/effects/GrBitmapTextGeoProc.cpp3
-rw-r--r--src/gpu/effects/GrDistanceFieldGeoProc.cpp9
-rw-r--r--src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp38
7 files changed, 174 insertions, 24 deletions
diff --git a/gn/samples.gni b/gn/samples.gni
index 6e1bcac893..7c0d9e2617 100644
--- a/gn/samples.gni
+++ b/gn/samples.gni
@@ -48,6 +48,7 @@ samples_sources = [
"$_samplecode/SampleFilter2.cpp",
"$_samplecode/SampleFilterFuzz.cpp",
"$_samplecode/SampleFilterQuality.cpp",
+ "$_samplecode/SampleFlutterAnimate.cpp",
"$_samplecode/SampleFontScalerTest.cpp",
"$_samplecode/SampleFuzz.cpp",
"$_samplecode/SampleGradients.cpp",
diff --git a/samplecode/SampleFlutterAnimate.cpp b/samplecode/SampleFlutterAnimate.cpp
new file mode 100644
index 0000000000..63b453b240
--- /dev/null
+++ b/samplecode/SampleFlutterAnimate.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SampleCode.h"
+#include "SkAnimTimer.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkUtils.h"
+#include "SkColorPriv.h"
+#include "SkColorFilter.h"
+#include "SkImage.h"
+#include "SkRandom.h"
+#include "SkSystemEventTypes.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "Timer.h"
+
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+#endif
+
+class FlutterAnimateView : public SampleView {
+public:
+ FlutterAnimateView() : fCurrTime(0), fResetTime(0) {}
+
+protected:
+ void onOnceBeforeDraw() override {
+ initChars();
+ }
+
+ // overrides from SkEventSink
+ bool onQuery(SkEvent* evt) override {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "FlutterAnimate");
+ return true;
+ }
+
+ return this->INHERITED::onQuery(evt);
+ }
+
+ void onDrawContent(SkCanvas* canvas) override {
+ SkPaint paint;
+ paint.setTypeface(SkTypeface::MakeFromFile("/skimages/samplefont.ttf"));
+ paint.setAntiAlias(true);
+ paint.setFilterQuality(kMedium_SkFilterQuality);
+ paint.setTextSize(50);
+
+ canvas->clear(SK_ColorWHITE);
+ for (int i = 0; i < kNumChars; ++i) {
+ canvas->save();
+ double rot = fChars[i].fStartRotation + (fChars[i].fEndRotation - fChars[i].fStartRotation)*fCurrTime/kDuration;
+ canvas->translate(fChars[i].fPosition.fX + 35,fChars[i].fPosition.fY - 50);
+ canvas->rotate(rot*180.0/SK_MScalarPI);
+ canvas->translate(-35,+50);
+ canvas->drawString(fChars[i].fChar, 0, 0,
+ paint);
+ canvas->restore();
+ }
+ }
+
+ bool onAnimate(const SkAnimTimer& timer) override {
+ fCurrTime = timer.secs() - fResetTime;
+ if (fCurrTime > kDuration) {
+ this->initChars();
+ fResetTime = timer.secs();
+ fCurrTime = 0;
+ }
+
+ return true;
+ }
+
+private:
+ void initChars() {
+ for (int i = 0; i < kNumChars; ++i) {
+ char c = fRand.nextULessThan(26) + 65;
+ fChars[i].fChar.set(&c, 1);
+ fChars[i].fPosition = SkPoint::Make(fRand.nextF()*748 + 10, fRand.nextF()*1004 + 10);
+ fChars[i].fStartRotation = fRand.nextF();
+ fChars[i].fEndRotation = fRand.nextF() * 20 - 10;
+ }
+ }
+
+ static constexpr double kDuration = 5.0;
+ double fCurrTime;
+ double fResetTime;
+ SkRandom fRand;
+
+ struct AnimatedChar {
+ SkString fChar;
+ SkPoint fPosition;
+ SkScalar fStartRotation;
+ SkScalar fEndRotation;
+ };
+ static constexpr int kNumChars = 40;
+ AnimatedChar fChars[kNumChars];
+
+ typedef SampleView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new FlutterAnimateView; }
+static SkViewRegister reg(MyFactory);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 68cf42ef2a..69acd15cb2 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -211,20 +211,12 @@ bool GrContext::init(const GrContextOptions& options) {
new GrDrawingManager(this, prcOptions, atlasTextContextOptions, &fSingleOwner));
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
- switch (options.fAllowMultipleGlyphCacheTextures) {
- case GrContextOptions::Enable::kDefault:
-#ifdef SK_BUILD_FOR_IOS
- allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
-#else
- allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
-#endif
- break;
- case GrContextOptions::Enable::kNo:
- allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
- break;
- case GrContextOptions::Enable::kYes:
- allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
- break;
+ if (GrContextOptions::Enable::kNo == options.fAllowMultipleGlyphCacheTextures ||
+ // multitexturing supported only if range can represent the index + texcoords fully
+ !(fCaps->shaderCaps()->floatIs32Bits() || fCaps->shaderCaps()->integerSupport())) {
+ allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
+ } else {
+ allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
}
fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes,
allowMultitexturing);
diff --git a/src/gpu/effects/GrAtlasedShaderHelpers.h b/src/gpu/effects/GrAtlasedShaderHelpers.h
index ad901411db..7fc321daa2 100644
--- a/src/gpu/effects/GrAtlasedShaderHelpers.h
+++ b/src/gpu/effects/GrAtlasedShaderHelpers.h
@@ -8,6 +8,7 @@
#ifndef GrAtlasedShaderHelpers_DEFINED
#define GrAtlasedShaderHelpers_DEFINED
+#include "GrShaderCaps.h"
#include "glsl/GrGLSLPrimitiveProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVarying.h"
@@ -22,17 +23,24 @@ static void append_index_uv_varyings(GrGLSLPrimitiveProcessor::EmitArgs& args,
// This extracts the texture index and texel coordinates from the same variable
// Packing structure: texel coordinates are multiplied by 2 (or shifted left 1)
// texture index is stored as lower bits of both x and y
- args.fVertBuilder->codeAppendf("half2 indexTexCoords = half2(%s.x, %s.y);",
- inTexCoordsName, inTexCoordsName);
- args.fVertBuilder->codeAppend("half2 intCoords = floor(0.5*indexTexCoords);");
- args.fVertBuilder->codeAppend("half2 diff = indexTexCoords - 2.0*intCoords;");
- args.fVertBuilder->codeAppend("half texIdx = 2.0*diff.x + diff.y;");
+ if (args.fShaderCaps->integerSupport()) {
+ args.fVertBuilder->codeAppendf("int2 signedCoords = int2(%s);", inTexCoordsName);
+ args.fVertBuilder->codeAppend("int texIdx = 2*(signedCoords.x & 0x1) + (signedCoords.y & 0x1);");
+ args.fVertBuilder->codeAppend("signedCoords >>= 1;");
+ args.fVertBuilder->codeAppend("float2 intCoords = float2(signedCoords);");
+ } else {
+ args.fVertBuilder->codeAppendf("float2 indexTexCoords = float2(%s.x, %s.y);",
+ inTexCoordsName, inTexCoordsName);
+ args.fVertBuilder->codeAppend("float2 intCoords = floor(0.5*indexTexCoords);");
+ args.fVertBuilder->codeAppend("float2 diff = indexTexCoords - 2.0*intCoords;");
+ args.fVertBuilder->codeAppend("float texIdx = 2.0*diff.x + diff.y;");
+ }
// Multiply by 1/atlasSize to get normalized texture coordinates
args.fVaryingHandler->addVarying("TextureCoords", uv);
args.fVertBuilder->codeAppendf("%s = intCoords * %s;", uv->vsOut(), atlasSizeInvName);
- args.fVaryingHandler->addVarying("TexIndex", texIdx);
+ args.fVaryingHandler->addFlatVarying("TexIndex", texIdx);
args.fVertBuilder->codeAppendf("%s = texIdx;", texIdx->vsOut());
if (st) {
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index d5f930fec4..4193f1d24c 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -38,7 +38,8 @@ public:
&atlasSizeInvName);
GrGLSLVertToFrag uv(kFloat2_GrSLType);
- GrGLSLVertToFrag texIdx(kHalf_GrSLType);
+ GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
+ GrGLSLVertToFrag texIdx(texIdxType);
append_index_uv_varyings(args, btgp.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, nullptr);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index aafabdeb60..3e9addef6d 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -78,7 +78,8 @@ public:
// add varyings
GrGLSLVertToFrag uv(kFloat2_GrSLType);
- GrGLSLVertToFrag texIdx(kHalf_GrSLType);
+ GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
+ GrGLSLVertToFrag texIdx(texIdxType);
GrGLSLVertToFrag st(kFloat2_GrSLType);
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, &st);
@@ -344,7 +345,8 @@ public:
&atlasSizeInvName);
GrGLSLVertToFrag uv(kFloat2_GrSLType);
- GrGLSLVertToFrag texIdx(kHalf_GrSLType);
+ GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
+ GrGLSLVertToFrag texIdx(texIdxType);
GrGLSLVertToFrag st(kFloat2_GrSLType);
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, &st);
@@ -639,7 +641,8 @@ public:
// set up varyings
GrGLSLVertToFrag uv(kFloat2_GrSLType);
- GrGLSLVertToFrag texIdx(kHalf_GrSLType);
+ GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
+ GrGLSLVertToFrag texIdx(texIdxType);
GrGLSLVertToFrag st(kFloat2_GrSLType);
append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->fName, atlasSizeInvName,
&uv, &texIdx, &st);
diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
index 28b2e0f0c0..81ae09a6f5 100644
--- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
+++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
@@ -38,6 +38,9 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
bool useDistanceFields, SkScalar transX, SkScalar transY,
GrColor color) {
uint16_t u0, v0, u1, v1;
+#ifdef DISPLAY_PAGE_INDEX
+ SkColor hackColor;
+#endif
if (regenTexCoords) {
SkASSERT(glyph);
int width = glyph->fBounds.width();
@@ -67,6 +70,25 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
u1 |= uBit;
v1 <<= 1;
v1 |= vBit;
+#ifdef DISPLAY_PAGE_INDEX
+ switch (pageIndex) {
+ case 0:
+ hackColor = SK_ColorGREEN;
+ break;
+ case 1:
+ hackColor = SK_ColorRED;
+ break;
+ case 2:
+ hackColor = SK_ColorMAGENTA;
+ break;
+ case 3:
+ hackColor = SK_ColorCYAN;
+ break;
+ default:
+ hackColor = SK_ColorBLACK;
+ break;
+ }
+#endif
}
// This is a bit wonky, but sometimes we have LCD text, in which case we won't have color
@@ -90,6 +112,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
textureCoords[0] = u0;
textureCoords[1] = v0;
+#ifdef DISPLAY_PAGE_INDEX
+ SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
+ *vcolor = hackColor;
+#endif
}
vertex += vertexStride;
@@ -109,6 +135,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
textureCoords[0] = u0;
textureCoords[1] = v1;
+#ifdef DISPLAY_PAGE_INDEX
+ SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
+ *vcolor = hackColor;
+#endif
}
vertex += vertexStride;
@@ -128,6 +158,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
textureCoords[0] = u1;
textureCoords[1] = v0;
+#ifdef DISPLAY_PAGE_INDEX
+ SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
+ *vcolor = hackColor;
+#endif
}
vertex += vertexStride;
@@ -147,6 +181,10 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
textureCoords[0] = u1;
textureCoords[1] = v1;
+#ifdef DISPLAY_PAGE_INDEX
+ SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
+ *vcolor = hackColor;
+#endif
}
}