aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gypi1
-rw-r--r--include/gpu/GrTestUtils.h1
-rw-r--r--src/gpu/GrTestUtils.cpp14
-rw-r--r--src/gpu/batches/GrNonAAFillRectBatch.cpp179
-rw-r--r--src/gpu/batches/GrNonAAFillRectPerspectiveBatch.cpp270
5 files changed, 282 insertions, 183 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 3cc89c0a8d..4a8deca6bd 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -246,6 +246,7 @@
'<(skia_src_path)/gpu/batches/GrMSAAPathRenderer.h',
'<(skia_src_path)/gpu/batches/GrNonAAFillRectBatch.h',
'<(skia_src_path)/gpu/batches/GrNonAAFillRectBatch.cpp',
+ '<(skia_src_path)/gpu/batches/GrNonAAFillRectPerspectiveBatch.cpp',
'<(skia_src_path)/gpu/batches/GrNonAAStrokeRectBatch.cpp',
'<(skia_src_path)/gpu/batches/GrNonAAStrokeRectBatch.h',
'<(skia_src_path)/gpu/batches/GrNinePatch.cpp',
diff --git a/include/gpu/GrTestUtils.h b/include/gpu/GrTestUtils.h
index caaf5d9785..89ac68ae3d 100644
--- a/include/gpu/GrTestUtils.h
+++ b/include/gpu/GrTestUtils.h
@@ -32,6 +32,7 @@ const SkMatrix& TestMatrix(SkRandom*);
const SkMatrix& TestMatrixPreservesRightAngles(SkRandom*);
const SkMatrix& TestMatrixRectStaysRect(SkRandom*);
const SkMatrix& TestMatrixInvertible(SkRandom*);
+const SkMatrix& TestMatrixPerspective(SkRandom*);
const SkRect& TestRect(SkRandom*);
const SkRect& TestSquare(SkRandom*);
const SkRRect& TestRRectSimple(SkRandom*);
diff --git a/src/gpu/GrTestUtils.cpp b/src/gpu/GrTestUtils.cpp
index e962978fc3..d5cdbab1fb 100644
--- a/src/gpu/GrTestUtils.cpp
+++ b/src/gpu/GrTestUtils.cpp
@@ -14,7 +14,9 @@
#ifdef GR_TEST_UTILS
-static const SkMatrix& test_matrix(SkRandom* random, bool includePerspective) {
+static const SkMatrix& test_matrix(SkRandom* random,
+ bool includeNonPerspective,
+ bool includePerspective) {
static SkMatrix gMatrices[5];
static const int kPerspectiveCount = 1;
static bool gOnce;
@@ -34,15 +36,18 @@ static const SkMatrix& test_matrix(SkRandom* random, bool includePerspective) {
}
uint32_t count = static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices));
- if (includePerspective) {
+ if (includeNonPerspective && includePerspective) {
return gMatrices[random->nextULessThan(count)];
+ } else if (!includeNonPerspective) {
+ return gMatrices[count - 1 - random->nextULessThan(kPerspectiveCount)];
} else {
+ SkASSERT(includeNonPerspective && !includePerspective);
return gMatrices[random->nextULessThan(count - kPerspectiveCount)];
}
}
namespace GrTest {
-const SkMatrix& TestMatrix(SkRandom* random) { return test_matrix(random, true); }
+const SkMatrix& TestMatrix(SkRandom* random) { return test_matrix(random, true, true); }
const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) {
static SkMatrix gMatrices[5];
@@ -96,7 +101,8 @@ const SkMatrix& TestMatrixRectStaysRect(SkRandom* random) {
return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
}
-const SkMatrix& TestMatrixInvertible(SkRandom* random) { return test_matrix(random, false); }
+const SkMatrix& TestMatrixInvertible(SkRandom* random) { return test_matrix(random, true, false); }
+const SkMatrix& TestMatrixPerspective(SkRandom* random) { return test_matrix(random, false, true); }
const SkRect& TestRect(SkRandom* random) {
static SkRect gRects[7];
diff --git a/src/gpu/batches/GrNonAAFillRectBatch.cpp b/src/gpu/batches/GrNonAAFillRectBatch.cpp
index 4a7daf2b79..aaeabdaeb7 100644
--- a/src/gpu/batches/GrNonAAFillRectBatch.cpp
+++ b/src/gpu/batches/GrNonAAFillRectBatch.cpp
@@ -26,35 +26,6 @@ static const int kIndicesPerInstance = 6;
The vertex attrib order is always pos, color, [local coords].
*/
-static sk_sp<GrGeometryProcessor> make_persp_gp(const SkMatrix& viewMatrix,
- bool readsCoverage,
- bool hasExplicitLocalCoords,
- const SkMatrix* localMatrix) {
- SkASSERT(viewMatrix.hasPerspective() || (localMatrix && localMatrix->hasPerspective()));
-
- using namespace GrDefaultGeoProcFactory;
- Color color(Color::kAttribute_Type);
- Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type);
-
- // If we have perspective on the viewMatrix then we won't map on the CPU, nor will we map
- // the local rect on the cpu (in case the localMatrix also has perspective).
- // Otherwise, if we have a local rect, then we apply the localMatrix directly to the localRect
- // to generate vertex local coords
- if (viewMatrix.hasPerspective()) {
- LocalCoords localCoords(hasExplicitLocalCoords ? LocalCoords::kHasExplicit_Type :
- LocalCoords::kUsePosition_Type,
- localMatrix);
- return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, viewMatrix);
- } else if (hasExplicitLocalCoords) {
- LocalCoords localCoords(LocalCoords::kHasExplicit_Type, localMatrix);
- return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
- } else {
- LocalCoords localCoords(LocalCoords::kUsePosition_Type, localMatrix);
- return GrDefaultGeoProcFactory::MakeForDeviceSpace(color, coverage, localCoords,
- viewMatrix);
- }
-}
-
static sk_sp<GrGeometryProcessor> make_gp(bool readsCoverage) {
using namespace GrDefaultGeoProcFactory;
Color color(Color::kAttribute_Type);
@@ -216,148 +187,6 @@ private:
typedef GrVertexBatch INHERITED;
};
-// We handle perspective in the local matrix or viewmatrix with special batches
-class NonAAFillRectPerspectiveBatch : public GrVertexBatch {
-public:
- DEFINE_BATCH_CLASS_ID
-
- NonAAFillRectPerspectiveBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
- const SkRect* localRect, const SkMatrix* localMatrix)
- : INHERITED(ClassID())
- , fViewMatrix(viewMatrix) {
- SkASSERT(viewMatrix.hasPerspective() || (localMatrix &&
- localMatrix->hasPerspective()));
- RectInfo& info = fRects.push_back();
- info.fColor = color;
- info.fRect = rect;
- fHasLocalRect = SkToBool(localRect);
- fHasLocalMatrix = SkToBool(localMatrix);
- if (fHasLocalMatrix) {
- fLocalMatrix = *localMatrix;
- }
- if (fHasLocalRect) {
- info.fLocalRect = *localRect;
- }
- viewMatrix.mapRect(&fBounds, rect);
- }
-
- const char* name() const override { return "NonAAFillRectPerspectiveBatch"; }
-
- SkString dumpInfo() const override {
- SkString str;
- str.appendf("# batched: %d\n", fRects.count());
- for (int i = 0; i < fRects.count(); ++i) {
- const RectInfo& geo = fRects[0];
- str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
- i, geo.fColor,
- geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
- }
- str.append(INHERITED::dumpInfo());
- return str;
- }
-
- void computePipelineOptimizations(GrInitInvariantOutput* color,
- GrInitInvariantOutput* coverage,
- GrBatchToXPOverrides* overrides) const override {
- // When this is called on a batch, there is only one geometry bundle
- color->setKnownFourComponents(fRects[0].fColor);
- coverage->setKnownSingleComponent(0xff);
- }
-
- void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
- overrides.getOverrideColorIfSet(&fRects[0].fColor);
- fOverrides = overrides;
- }
-
-private:
- NonAAFillRectPerspectiveBatch() : INHERITED(ClassID()) {}
-
- void onPrepareDraws(Target* target) const override {
- sk_sp<GrGeometryProcessor> gp = make_persp_gp(fViewMatrix,
- fOverrides.readsCoverage(),
- fHasLocalRect,
- fHasLocalMatrix ? &fLocalMatrix : nullptr);
- if (!gp) {
- SkDebugf("Couldn't create GrGeometryProcessor\n");
- return;
- }
- SkASSERT(fHasLocalRect
- ? gp->getVertexStride() ==
- sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr)
- : gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
-
- size_t vertexStride = gp->getVertexStride();
- int instanceCount = fRects.count();
-
- SkAutoTUnref<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
- InstancedHelper helper;
- void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
- indexBuffer, kVertsPerInstance,
- kIndicesPerInstance, instanceCount);
- if (!vertices || !indexBuffer) {
- SkDebugf("Could not allocate vertices\n");
- return;
- }
-
- for (int i = 0; i < instanceCount; i++) {
- const RectInfo& info = fRects[i];
- intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
- i * kVertsPerInstance * vertexStride;
- if (fHasLocalRect) {
- GrQuad quad(info.fLocalRect);
- tesselate(verts, vertexStride, info.fColor, nullptr, info.fRect, &quad);
- } else {
- tesselate(verts, vertexStride, info.fColor, nullptr, info.fRect, nullptr);
- }
- }
- helper.recordDraw(target, gp.get());
- }
-
- bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
- NonAAFillRectPerspectiveBatch* that = t->cast<NonAAFillRectPerspectiveBatch>();
- if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
- that->bounds(), caps)) {
- return false;
- }
-
- // We could batch across perspective vm changes if we really wanted to
- if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
- return false;
- }
- if (fHasLocalRect != that->fHasLocalRect) {
- return false;
- }
- if (fHasLocalMatrix && !fLocalMatrix.cheapEqualTo(that->fLocalMatrix)) {
- return false;
- }
-
- // In the event of two batches, one who can tweak, one who cannot, we just fall back to
- // not tweaking
- if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
- fOverrides = that->fOverrides;
- }
-
- fRects.push_back_n(that->fRects.count(), that->fRects.begin());
- this->joinBounds(that->bounds());
- return true;
- }
-
- struct RectInfo {
- SkRect fRect;
- GrColor fColor;
- SkRect fLocalRect;
- };
-
- GrXPOverridesForBatch fOverrides;
- SkSTArray<1, RectInfo, true> fRects;
- bool fHasLocalMatrix;
- bool fHasLocalRect;
- SkMatrix fLocalMatrix;
- SkMatrix fViewMatrix;
-
- typedef GrVertexBatch INHERITED;
-};
-
namespace GrNonAAFillRectBatch {
GrDrawBatch* Create(GrColor color,
@@ -368,14 +197,6 @@ GrDrawBatch* Create(GrColor color,
return new NonAAFillRectBatch(color, viewMatrix, rect, localRect, localMatrix);
}
-GrDrawBatch* CreateWithPerspective(GrColor color,
- const SkMatrix& viewMatrix,
- const SkRect& rect,
- const SkRect* localRect,
- const SkMatrix* localMatrix) {
- return new NonAAFillRectPerspectiveBatch(color, viewMatrix, rect, localRect, localMatrix);
-}
-
};
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/batches/GrNonAAFillRectPerspectiveBatch.cpp b/src/gpu/batches/GrNonAAFillRectPerspectiveBatch.cpp
new file mode 100644
index 0000000000..3cff209840
--- /dev/null
+++ b/src/gpu/batches/GrNonAAFillRectPerspectiveBatch.cpp
@@ -0,0 +1,270 @@
+/*
+ * 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 "GrNonAAFillRectBatch.h"
+
+#include "GrBatchFlushState.h"
+#include "GrColor.h"
+#include "GrDefaultGeoProcFactory.h"
+#include "GrPrimitiveProcessor.h"
+#include "GrResourceProvider.h"
+#include "GrQuad.h"
+#include "GrVertexBatch.h"
+
+static const int kVertsPerInstance = 4;
+static const int kIndicesPerInstance = 6;
+
+/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes
+ we have explicit local coords and sometimes not. We *could* always provide explicit local
+ coords and just duplicate the positions when the caller hasn't provided a local coord rect,
+ but we haven't seen a use case which frequently switches between local rect and no local
+ rect draws.
+
+ The vertex attrib order is always pos, color, [local coords].
+ */
+static sk_sp<GrGeometryProcessor> make_persp_gp(const SkMatrix& viewMatrix,
+ bool readsCoverage,
+ bool hasExplicitLocalCoords,
+ const SkMatrix* localMatrix) {
+ SkASSERT(viewMatrix.hasPerspective() || (localMatrix && localMatrix->hasPerspective()));
+
+ using namespace GrDefaultGeoProcFactory;
+ Color color(Color::kAttribute_Type);
+ Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type);
+
+ // If we have perspective on the viewMatrix then we won't map on the CPU, nor will we map
+ // the local rect on the cpu (in case the localMatrix also has perspective).
+ // Otherwise, if we have a local rect, then we apply the localMatrix directly to the localRect
+ // to generate vertex local coords
+ if (viewMatrix.hasPerspective()) {
+ LocalCoords localCoords(hasExplicitLocalCoords ? LocalCoords::kHasExplicit_Type :
+ LocalCoords::kUsePosition_Type,
+ localMatrix);
+ return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, viewMatrix);
+ } else if (hasExplicitLocalCoords) {
+ LocalCoords localCoords(LocalCoords::kHasExplicit_Type, localMatrix);
+ return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
+ } else {
+ LocalCoords localCoords(LocalCoords::kUsePosition_Type, localMatrix);
+ return GrDefaultGeoProcFactory::MakeForDeviceSpace(color, coverage, localCoords,
+ viewMatrix);
+ }
+}
+
+static void tesselate(intptr_t vertices,
+ size_t vertexStride,
+ GrColor color,
+ const SkMatrix* viewMatrix,
+ const SkRect& rect,
+ const GrQuad* localQuad) {
+ SkPoint* positions = reinterpret_cast<SkPoint*>(vertices);
+
+ positions->setRectFan(rect.fLeft, rect.fTop,
+ rect.fRight, rect.fBottom, vertexStride);
+
+ if (viewMatrix) {
+ viewMatrix->mapPointsWithStride(positions, vertexStride, kVertsPerInstance);
+ }
+
+ // Setup local coords
+ // TODO we should only do this if local coords are being read
+ if (localQuad) {
+ static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
+ for (int i = 0; i < kVertsPerInstance; i++) {
+ SkPoint* coords = reinterpret_cast<SkPoint*>(vertices + kLocalOffset +
+ i * vertexStride);
+ *coords = localQuad->point(i);
+ }
+ }
+
+ static const int kColorOffset = sizeof(SkPoint);
+ GrColor* vertColor = reinterpret_cast<GrColor*>(vertices + kColorOffset);
+ for (int j = 0; j < 4; ++j) {
+ *vertColor = color;
+ vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
+ }
+}
+
+// We handle perspective in the local matrix or viewmatrix with special batches
+class GrNonAAFillRectPerspectiveBatch : public GrVertexBatch {
+public:
+ DEFINE_BATCH_CLASS_ID
+
+ GrNonAAFillRectPerspectiveBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
+ const SkRect* localRect, const SkMatrix* localMatrix)
+ : INHERITED(ClassID())
+ , fViewMatrix(viewMatrix) {
+ SkASSERT(viewMatrix.hasPerspective() || (localMatrix &&
+ localMatrix->hasPerspective()));
+ RectInfo& info = fRects.push_back();
+ info.fColor = color;
+ info.fRect = rect;
+ fHasLocalRect = SkToBool(localRect);
+ fHasLocalMatrix = SkToBool(localMatrix);
+ if (fHasLocalMatrix) {
+ fLocalMatrix = *localMatrix;
+ }
+ if (fHasLocalRect) {
+ info.fLocalRect = *localRect;
+ }
+ viewMatrix.mapRect(&fBounds, rect);
+ }
+
+ const char* name() const override { return "NonAAFillRectPerspectiveBatch"; }
+
+ SkString dumpInfo() const override {
+ SkString str;
+ str.appendf("# batched: %d\n", fRects.count());
+ for (int i = 0; i < fRects.count(); ++i) {
+ const RectInfo& geo = fRects[0];
+ str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
+ i, geo.fColor,
+ geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
+ }
+ str.append(INHERITED::dumpInfo());
+ return str;
+ }
+
+ void computePipelineOptimizations(GrInitInvariantOutput* color,
+ GrInitInvariantOutput* coverage,
+ GrBatchToXPOverrides* overrides) const override {
+ // When this is called on a batch, there is only one geometry bundle
+ color->setKnownFourComponents(fRects[0].fColor);
+ coverage->setKnownSingleComponent(0xff);
+ }
+
+ void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
+ overrides.getOverrideColorIfSet(&fRects[0].fColor);
+ fOverrides = overrides;
+ }
+
+private:
+ GrNonAAFillRectPerspectiveBatch() : INHERITED(ClassID()) {}
+
+ void onPrepareDraws(Target* target) const override {
+ sk_sp<GrGeometryProcessor> gp = make_persp_gp(fViewMatrix,
+ fOverrides.readsCoverage(),
+ fHasLocalRect,
+ fHasLocalMatrix ? &fLocalMatrix : nullptr);
+ if (!gp) {
+ SkDebugf("Couldn't create GrGeometryProcessor\n");
+ return;
+ }
+ SkASSERT(fHasLocalRect
+ ? gp->getVertexStride() ==
+ sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr)
+ : gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
+
+ size_t vertexStride = gp->getVertexStride();
+ int instanceCount = fRects.count();
+
+ SkAutoTUnref<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
+ InstancedHelper helper;
+ void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
+ indexBuffer, kVertsPerInstance,
+ kIndicesPerInstance, instanceCount);
+ if (!vertices || !indexBuffer) {
+ SkDebugf("Could not allocate vertices\n");
+ return;
+ }
+
+ for (int i = 0; i < instanceCount; i++) {
+ const RectInfo& info = fRects[i];
+ intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
+ i * kVertsPerInstance * vertexStride;
+ if (fHasLocalRect) {
+ GrQuad quad(info.fLocalRect);
+ tesselate(verts, vertexStride, info.fColor, nullptr, info.fRect, &quad);
+ } else {
+ tesselate(verts, vertexStride, info.fColor, nullptr, info.fRect, nullptr);
+ }
+ }
+ helper.recordDraw(target, gp.get());
+ }
+
+ bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
+ GrNonAAFillRectPerspectiveBatch* that = t->cast<GrNonAAFillRectPerspectiveBatch>();
+ if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
+ that->bounds(), caps)) {
+ return false;
+ }
+
+ // We could batch across perspective vm changes if we really wanted to
+ if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
+ return false;
+ }
+ if (fHasLocalRect != that->fHasLocalRect) {
+ return false;
+ }
+ if (fHasLocalMatrix && !fLocalMatrix.cheapEqualTo(that->fLocalMatrix)) {
+ return false;
+ }
+
+ // In the event of two batches, one who can tweak, one who cannot, we just fall back to
+ // not tweaking
+ if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
+ fOverrides = that->fOverrides;
+ }
+
+ fRects.push_back_n(that->fRects.count(), that->fRects.begin());
+ this->joinBounds(that->bounds());
+ return true;
+ }
+
+ struct RectInfo {
+ SkRect fRect;
+ GrColor fColor;
+ SkRect fLocalRect;
+ };
+
+ GrXPOverridesForBatch fOverrides;
+ SkSTArray<1, RectInfo, true> fRects;
+ bool fHasLocalMatrix;
+ bool fHasLocalRect;
+ SkMatrix fLocalMatrix;
+ SkMatrix fViewMatrix;
+
+ typedef GrVertexBatch INHERITED;
+};
+
+namespace GrNonAAFillRectBatch {
+
+GrDrawBatch* CreateWithPerspective(GrColor color,
+ const SkMatrix& viewMatrix,
+ const SkRect& rect,
+ const SkRect* localRect,
+ const SkMatrix* localMatrix) {
+ return new GrNonAAFillRectPerspectiveBatch(color, viewMatrix, rect, localRect, localMatrix);
+}
+
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef GR_TEST_UTILS
+
+#include "GrBatchTest.h"
+
+DRAW_BATCH_TEST_DEFINE(PerspRectBatch) {
+ GrColor color = GrRandomColor(random);
+ SkRect rect = GrTest::TestRect(random);
+ SkRect localRect = GrTest::TestRect(random);
+ SkMatrix viewMatrix = GrTest::TestMatrix(random);
+ bool hasLocalMatrix = random->nextBool();
+ SkMatrix localMatrix;
+ if (!viewMatrix.hasPerspective()) {
+ localMatrix = GrTest::TestMatrixPerspective(random);
+ hasLocalMatrix = true;
+ }
+
+ bool hasLocalRect = random->nextBool();
+ return GrNonAAFillRectBatch::CreateWithPerspective(color, viewMatrix, rect,
+ hasLocalRect ? &localRect : nullptr,
+ hasLocalMatrix ? &localMatrix : nullptr);
+}
+
+#endif