aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/PatchGridBench.cpp258
-rw-r--r--gm/patchgrid.cpp159
-rw-r--r--gn/bench.gni1
-rw-r--r--gn/gm.gni1
-rw-r--r--gn/utils.gni2
-rw-r--r--src/core/SkDevice.cpp10
-rw-r--r--src/utils/SkPatchGrid.cpp189
-rw-r--r--src/utils/SkPatchGrid.h142
-rw-r--r--src/utils/SkPatchUtils.cpp146
-rw-r--r--src/utils/SkPatchUtils.h6
10 files changed, 155 insertions, 759 deletions
diff --git a/bench/PatchGridBench.cpp b/bench/PatchGridBench.cpp
deleted file mode 100644
index 9892658dcd..0000000000
--- a/bench/PatchGridBench.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Benchmark.h"
-#include "SkCanvas.h"
-#include "SkGradientShader.h"
-#include "SkPaint.h"
-#include "SkPatchGrid.h"
-#include "SkString.h"
-
- /**
- * This bench measures the rendering time of a gridof patches.
- * This bench also tests the different combination of optional parameters for the function
- * (passing texture coordinates and colors, only textures coordinates, only colors or none).
- * Finally, it also has 3 possible sizes small, medium and big to test if the size of the patches
- * in the grid affects time.
- */
-
-class PatchGridBench : public Benchmark {
-
-public:
-
- enum Size {
- kSmall_Size,
- kMedium_Size,
- kBig_Size
- };
-
- enum VertexMode {
- kNone_VertexMode,
- kColors_VertexMode,
- kTexCoords_VertexMode,
- kBoth_VertexMode
- };
-
- PatchGridBench(Size size, VertexMode vertexMode)
- : fVertexMode(vertexMode)
- , fSize(size) { }
-
- void setScale(SkCanvas* canvas){
- switch (fSize) {
- case kSmall_Size:
- canvas->scale(0.1f, 0.1f);
- break;
- case kMedium_Size:
- canvas->scale(1.0f, 1.0f);
- break;
- case kBig_Size:
- canvas->scale(3.0f, 3.0f);
- break;
- }
- }
-
- void setGrid() {
- SkPoint vertices[4][5] = {
- {{50,50}, {150,50}, {250,50},{350,50},{450,50}},
- {{50,150}, {120,120}, {250,150},{350,150},{450,150}},
- {{50,250}, {150,250}, {250,250},{350,250},{450,250}},
- {{100,300}, {150,350}, {250,350},{350,350},{450,350}}
- };
-
- SkColor cornerColors[4][5] = {
- {SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
- {SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
- {SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
- {SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
- };
-
- SkPoint texCoords[4][5] = {
- {{0.0f,0.0f}, {1.0f,0.0f}, {2.0f,0.0f}, {3.0f,0.0f}, {4.0f,0.0f}},
- {{0.0f,1.0f}, {1.0f,1.0f}, {2.0f,1.0f}, {3.0f,1.0f}, {4.0f,1.0f}},
- {{0.0f,2.0f}, {1.0f,2.0f}, {2.0f,2.0f}, {3.0f,2.0f}, {4.0f,2.0f}},
- {{0.0f,3.0f}, {1.0f,3.0f}, {2.0f,3.0f}, {3.0f,3.0f}, {4.0f,3.0f}},
- };
-
- SkPoint hrzCtrl[4][8] = {
- {{75,30},{125,45},{175,70},{225,20},{275,50},{325,50},{375,5},{425,90}},
- {{75,150},{125,150},{175,150},{225,150},{275,150},{325,150},{375,150},{425,150}},
- {{75,250},{125,250},{175,250},{225,250},{275,200},{325,150},{375,250},{425,250}},
- {{75,350},{125,350},{175,350},{225,350},{275,350},{325,350},{375,350},{425,350}}
- };
-
- SkPoint vrtCtrl[6][5] = {
- {{50,75},{150,75},{250,75},{350,75},{450,75}},
- {{50,125},{150,125},{250,125},{350,125},{450,125}},
- {{50,175},{150,175},{220,225},{350,175},{470,225}},
- {{50,225},{150,225},{220,175},{350,225},{470,155}},
- {{50,275},{150,275},{250,275},{350,275},{400,305}},
- {{50,325},{150,325},{250,325},{350,325},{450,325}}
- };
-
- static const int kRows = 3;
- static const int kCols = 4;
-
- fGrid.reset(kRows, kCols, SkPatchGrid::kColors_VertexType, SkBlendMode::kModulate);
- for (int i = 0; i < kRows; i++) {
- for (int j = 0; j < kCols; j++) {
- SkPoint points[12];
-
- //set corners
- points[SkPatchUtils::kTopP0_CubicCtrlPts] = vertices[i][j];
- points[SkPatchUtils::kTopP3_CubicCtrlPts] = vertices[i][j + 1];
- points[SkPatchUtils::kBottomP0_CubicCtrlPts] = vertices[i + 1][j];
- points[SkPatchUtils::kBottomP3_CubicCtrlPts] = vertices[i + 1][j + 1];
-
- points[SkPatchUtils::kTopP1_CubicCtrlPts] = hrzCtrl[i][j * 2];
- points[SkPatchUtils::kTopP2_CubicCtrlPts] = hrzCtrl[i][j * 2 + 1];
- points[SkPatchUtils::kBottomP1_CubicCtrlPts] = hrzCtrl[i + 1][j * 2];
- points[SkPatchUtils::kBottomP2_CubicCtrlPts] = hrzCtrl[i + 1][j * 2 + 1];
-
- points[SkPatchUtils::kLeftP1_CubicCtrlPts] = vrtCtrl[i * 2][j];
- points[SkPatchUtils::kLeftP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j];
- points[SkPatchUtils::kRightP1_CubicCtrlPts] = vrtCtrl[i * 2][j + 1];
- points[SkPatchUtils::kRightP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j + 1];
-
- SkColor colors[4];
- colors[0] = cornerColors[i][j];
- colors[1] = cornerColors[i][j + 1];
- colors[3] = cornerColors[i + 1][j];
- colors[2] = cornerColors[i + 1][j + 1];
-
- SkPoint texs[4];
- texs[0] = texCoords[i][j];
- texs[1] = texCoords[i][j + 1];
- texs[3] = texCoords[i + 1][j];
- texs[2] = texCoords[i + 1][j + 1];
-
- switch (fVertexMode) {
- case kNone_VertexMode:
- fGrid.setPatch(j, i, points, nullptr, nullptr);
- break;
- case kColors_VertexMode:
- fGrid.setPatch(j, i, points, colors, nullptr);
- break;
- case kTexCoords_VertexMode:
- fGrid.setPatch(j, i, points, nullptr, texs);
- break;
- case kBoth_VertexMode:
- fGrid.setPatch(j, i, points, colors, texs);
- break;
- default:
- break;
- }
- }
- }
- }
-
- // override this method to change the shader
- sk_sp<SkShader> createShader() {
- const SkColor colors[] = {
- SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE,
- SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW,
- };
- const SkPoint pts[] = { { 200.f / 4.f, 0.f }, { 3.f * 200.f / 4, 200.f } };
-
- return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
- SkShader::kMirror_TileMode);
- }
-
-protected:
- const char* onGetName() override {
- SkString vertexMode;
- switch (fVertexMode) {
- case kNone_VertexMode:
- vertexMode.set("meshlines");
- break;
- case kColors_VertexMode:
- vertexMode.set("colors");
- break;
- case kTexCoords_VertexMode:
- vertexMode.set("texs");
- break;
- case kBoth_VertexMode:
- vertexMode.set("colors_texs");
- break;
- default:
- break;
- }
-
- SkString size;
- switch (fSize) {
- case kSmall_Size:
- size.set("small");
- break;
- case kMedium_Size:
- size.set("medium");
- break;
- case kBig_Size:
- size.set("big");
- break;
- default:
- break;
- }
- fName.printf("patch_grid_%s_%s", vertexMode.c_str(), size.c_str());
- return fName.c_str();
- }
-
- void onDelayedSetup() override {
- this->setGrid();
- switch (fVertexMode) {
- case kTexCoords_VertexMode:
- case kBoth_VertexMode:
- fPaint.setShader(createShader());
- break;
- default:
- fPaint.setShader(nullptr);
- break;
- }
- this->setupPaint(&fPaint);
- }
-
- void onDraw(int loops, SkCanvas* canvas) override {
- this->setScale(canvas);
- for (int i = 0; i < loops; i++) {
- fGrid.draw(canvas, fPaint);
- }
- }
-
- SkPaint fPaint;
- SkString fName;
- SkPatchGrid fGrid;
- VertexMode fVertexMode;
- Size fSize;
-
- typedef Benchmark INHERITED;
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
- PatchGridBench::kNone_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
- PatchGridBench::kColors_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
- PatchGridBench::kTexCoords_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
- PatchGridBench::kBoth_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
- PatchGridBench::kNone_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
- PatchGridBench::kColors_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
- PatchGridBench::kTexCoords_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
- PatchGridBench::kBoth_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
- PatchGridBench::kNone_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
- PatchGridBench::kColors_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
- PatchGridBench::kTexCoords_VertexMode); )
-DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
- PatchGridBench::kBoth_VertexMode); )
diff --git a/gm/patchgrid.cpp b/gm/patchgrid.cpp
deleted file mode 100644
index 6f322312a6..0000000000
--- a/gm/patchgrid.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "gm.h"
-#include "SkPatchGrid.h"
-
-static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
- //draw control points
- SkPaint paint;
- SkPoint bottom[4];
- SkPatchUtils::getBottomCubic(cubics, bottom);
- SkPoint top[4];
- SkPatchUtils::getTopCubic(cubics, top);
- SkPoint left[4];
- SkPatchUtils::getLeftCubic(cubics, left);
- SkPoint right[4];
- SkPatchUtils::getRightCubic(cubics, right);
-
- paint.setColor(SK_ColorBLACK);
- paint.setStrokeWidth(0.5);
- SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
- canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom+1, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint);
-
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top+1, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left+1, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right+1, paint);
-
- paint.setStrokeWidth(2);
-
- paint.setColor(SK_ColorRED);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint);
-
- paint.setColor(SK_ColorBLUE);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom+1, paint);
-
- paint.setColor(SK_ColorCYAN);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top+1, paint);
-
- paint.setColor(SK_ColorYELLOW);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left+1, paint);
-
- paint.setColor(SK_ColorGREEN);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right+1, paint);
-}
-
-namespace skiagm {
-/**
- * This GM draws a grid of patches, it only uses colors so it could be considered a mesh gradient.
- */
-class SkPatchGridGM : public GM {
-
-public:
- SkPatchGridGM() {
- this->setBGColor(0xFFFFFFFF);
- }
-
-protected:
- SkString onShortName() override {
- return SkString("patch_grid");
- }
-
- SkISize onISize() override {
- return SkISize::Make(800, 800);
- }
-
- void onDraw(SkCanvas* canvas) override {
-
- SkPaint paint;
-
- SkPoint vertices[4][5] = {
- {{50,50}, {150,50}, {250,50},{350,50},{450,50}},
- {{50,150}, {120,120}, {250,150},{350,150},{450,150}},
- {{50,250}, {150,250}, {250,250},{350,250},{450,250}},
- {{100,300}, {150,350}, {250,350},{350,350},{450,350}}
- };
-
- SkColor cornerColors[4][5] = {
- {SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
- {SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
- {SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
- {SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
- };
-
- SkPoint hrzCtrl[4][8] = {
- {{75,30},{125,45},{175,70},{225,20},{275,50},{325,50},{375,5},{425,90}},
- {{75,150},{125,150},{175,150},{225,150},{275,150},{325,150},{375,150},{425,150}},
- {{75,250},{125,250},{175,250},{225,250},{275,200},{325,150},{375,250},{425,250}},
- {{75,350},{125,350},{175,350},{225,350},{275,350},{325,350},{375,350},{425,350}}
- };
-
- SkPoint vrtCtrl[6][5] = {
- {{50,75},{150,75},{250,75},{350,75},{450,75}},
- {{50,125},{150,125},{250,125},{350,125},{450,125}},
- {{50,175},{150,175},{220,225},{350,175},{470,225}},
- {{50,225},{150,225},{220,175},{350,225},{470,155}},
- {{50,275},{150,275},{250,275},{350,275},{400,305}},
- {{50,325},{150,325},{250,325},{350,325},{450,325}}
- };
-
- constexpr int kRows = 3;
- constexpr int kCols = 4;
-
- canvas->scale(3, 3);
- SkPatchGrid grid(kRows, kCols, SkPatchGrid::kColors_VertexType);
- for (int i = 0; i < kRows; i++) {
- for (int j = 0; j < kCols; j++) {
- SkPoint points[12];
-
- //set corners
- points[SkPatchUtils::kTopP0_CubicCtrlPts] = vertices[i][j];
- points[SkPatchUtils::kTopP3_CubicCtrlPts] = vertices[i][j + 1];
- points[SkPatchUtils::kBottomP0_CubicCtrlPts] = vertices[i + 1][j];
- points[SkPatchUtils::kBottomP3_CubicCtrlPts] = vertices[i + 1][j + 1];
-
- points[SkPatchUtils::kTopP1_CubicCtrlPts] = hrzCtrl[i][j * 2];
- points[SkPatchUtils::kTopP2_CubicCtrlPts] = hrzCtrl[i][j * 2 + 1];
- points[SkPatchUtils::kBottomP1_CubicCtrlPts] = hrzCtrl[i + 1][j * 2];
- points[SkPatchUtils::kBottomP2_CubicCtrlPts] = hrzCtrl[i + 1][j * 2 + 1];
-
- points[SkPatchUtils::kLeftP1_CubicCtrlPts] = vrtCtrl[i * 2][j];
- points[SkPatchUtils::kLeftP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j];
- points[SkPatchUtils::kRightP1_CubicCtrlPts] = vrtCtrl[i * 2][j + 1];
- points[SkPatchUtils::kRightP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j + 1];
-
- SkColor colors[4];
- colors[0] = cornerColors[i][j];
- colors[1] = cornerColors[i][j + 1];
- colors[3] = cornerColors[i + 1][j];
- colors[2] = cornerColors[i + 1][j + 1];
-
- grid.setPatch(j, i, points, colors, nullptr);
- }
- }
-
- grid.draw(canvas, paint);
- SkISize dims = grid.getDimensions();
- for (int y = 0; y < dims.height(); y++) {
- for (int x = 0; x < dims.width(); x++) {
- SkPoint cubics[12];
- grid.getPatch(x, y, cubics, nullptr, nullptr);
- draw_control_points(canvas, cubics);
- }
- }
- }
-
-private:
- typedef GM INHERITED;
-};
-
-DEF_GM(return new SkPatchGridGM;)
-}
diff --git a/gn/bench.gni b/gn/bench.gni
index 843964c789..cf6ce881b3 100644
--- a/gn/bench.gni
+++ b/gn/bench.gni
@@ -78,7 +78,6 @@ bench_sources = [
"$_bench/MutexBench.cpp",
"$_bench/pack_int_uint16_t_Bench.cpp",
"$_bench/PatchBench.cpp",
- "$_bench/PatchGridBench.cpp",
"$_bench/PathBench.cpp",
"$_bench/PathIterBench.cpp",
"$_bench/PDFBench.cpp",
diff --git a/gn/gm.gni b/gn/gm.gni
index 3b94be509e..65c6766ebb 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -207,7 +207,6 @@ gm_sources = [
"$_gm/overdrawcolorfilter.cpp",
"$_gm/OverStroke.cpp",
"$_gm/patch.cpp",
- "$_gm/patchgrid.cpp",
"$_gm/path_stroke_with_zero_length.cpp",
"$_gm/pathcontourstart.cpp",
"$_gm/patheffects.cpp",
diff --git a/gn/utils.gni b/gn/utils.gni
index 4dd09e81a6..4a3841b0b2 100644
--- a/gn/utils.gni
+++ b/gn/utils.gni
@@ -58,8 +58,6 @@ skia_utils_sources = [
"$_src/utils/SkParse.cpp",
"$_src/utils/SkParseColor.cpp",
"$_src/utils/SkParsePath.cpp",
- "$_src/utils/SkPatchGrid.cpp",
- "$_src/utils/SkPatchGrid.h",
"$_src/utils/SkPatchUtils.cpp",
"$_src/utils/SkPatchUtils.h",
"$_src/utils/SkRGBAToYUV.cpp",
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 44c9dfb75c..11a6a87fde 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -129,13 +129,9 @@ void SkBaseDevice::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
SkPatchUtils::VertexData data;
SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &this->ctm());
-
- // It automatically adjusts lodX and lodY in case it exceeds the number of indices.
- // If it fails to generate the vertices, then we do not draw.
- if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) {
- this->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
- data.fTexCoords, data.fColors, bmode, data.fIndices, data.fIndexCount,
- paint);
+ auto vertices = SkPatchUtils::MakeVertices(cubics, colors, texCoords, lod.width(), lod.height());
+ if (vertices) {
+ this->drawVerticesObject(vertices.get(), bmode, paint);
}
}
diff --git a/src/utils/SkPatchGrid.cpp b/src/utils/SkPatchGrid.cpp
deleted file mode 100644
index ee30ce1afe..0000000000
--- a/src/utils/SkPatchGrid.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPatchGrid.h"
-#include "SkPatchUtils.h"
-
-SkPatchGrid::SkPatchGrid(int rows, int cols, VertexType flags)
- : fRows(0)
- , fCols(0)
- , fModeFlags(kNone_VertexType)
- , fCornerPts(nullptr)
- , fCornerColors(nullptr)
- , fTexCoords(nullptr)
- , fHrzCtrlPts(nullptr)
- , fVrtCtrlPts(nullptr)
-{
- this->reset(rows, cols, flags, SkBlendMode::kModulate);
-}
-
-SkPatchGrid::~SkPatchGrid() {
- delete[] fCornerPts;
- delete[] fCornerColors;
- delete[] fTexCoords;
- delete[] fHrzCtrlPts;
- delete[] fVrtCtrlPts;
-}
-
-bool SkPatchGrid::setPatch(int x, int y, const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4]) {
- // Check for the passed paramaters to be within the range of the grid dimensions and a valid
- // pointer for the cubics' control points.
- if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || nullptr == cubics) {
- return false;
- }
-
- // setup corners and colors
- int cornerPos = y * (fCols + 1) + x;
- fCornerPts[cornerPos] = cubics[SkPatchUtils::kTopP0_CubicCtrlPts];
- fCornerPts[cornerPos + 1] = cubics[SkPatchUtils::kTopP3_CubicCtrlPts];
- fCornerPts[cornerPos + (fCols + 1)] = cubics[SkPatchUtils::kBottomP0_CubicCtrlPts];
- fCornerPts[cornerPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kBottomP3_CubicCtrlPts];
-
- // set horizontal control points
- int hrzPos = y * (fCols * 2) + (x * 2);
- fHrzCtrlPts[hrzPos] = cubics[SkPatchUtils::kTopP1_CubicCtrlPts];
- fHrzCtrlPts[hrzPos + 1] = cubics[SkPatchUtils::kTopP2_CubicCtrlPts];
- fHrzCtrlPts[hrzPos + (fCols * 2)] = cubics[SkPatchUtils::kBottomP1_CubicCtrlPts];
- fHrzCtrlPts[hrzPos + (fCols * 2) + 1] = cubics[SkPatchUtils::kBottomP2_CubicCtrlPts];
-
- // set vertical control points
- int vrtPos = (y*2) * (fCols + 1) + x;
- fVrtCtrlPts[vrtPos] = cubics[SkPatchUtils::kLeftP1_CubicCtrlPts];
- fVrtCtrlPts[vrtPos + 1] = cubics[SkPatchUtils::kRightP1_CubicCtrlPts];
- fVrtCtrlPts[vrtPos + (fCols + 1)] = cubics[SkPatchUtils::kLeftP2_CubicCtrlPts];
- fVrtCtrlPts[vrtPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kRightP2_CubicCtrlPts];
-
- // set optional values (colors and texture coordinates)
- if ((fModeFlags & kColors_VertexType) && colors) {
- fCornerColors[cornerPos] = colors[0];
- fCornerColors[cornerPos + 1] = colors[1];
- fCornerColors[cornerPos + (fCols + 1)] = colors[3];
- fCornerColors[cornerPos + (fCols + 1) + 1] = colors[2];
- }
-
- if ((fModeFlags & kTexs_VertexType) && texCoords) {
- fTexCoords[cornerPos] = texCoords[0];
- fTexCoords[cornerPos + 1] = texCoords[1];
- fTexCoords[cornerPos + (fCols + 1)] = texCoords[3];
- fTexCoords[cornerPos + (fCols + 1) + 1] = texCoords[2];
- }
-
- return true;
-}
-
-bool SkPatchGrid::getPatch(int x, int y, SkPoint cubics[12], SkColor colors[4],
- SkPoint texCoords[4]) const {
-
- if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || nullptr == cubics) {
- return false;
- }
-
- // set the patch by building the array of points and colors with the corresponding values.
- int cornerPos = y * (fCols + 1) + x;
- cubics[SkPatchUtils::kTopP0_CubicCtrlPts] = fCornerPts[cornerPos];
- cubics[SkPatchUtils::kTopP3_CubicCtrlPts] = fCornerPts[cornerPos + 1];
- cubics[SkPatchUtils::kBottomP0_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1)];
- cubics[SkPatchUtils::kBottomP3_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1) + 1];
-
- int hrzPos = y * (fCols * 2) + (x * 2);
- cubics[SkPatchUtils::kTopP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos];
- cubics[SkPatchUtils::kTopP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + 1];
- cubics[SkPatchUtils::kBottomP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2)];
- cubics[SkPatchUtils::kBottomP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2) + 1];
-
- int vrtPos = (y*2) * (fCols + 1) + x;
- cubics[SkPatchUtils::kLeftP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos];
- cubics[SkPatchUtils::kRightP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos + 1];
- cubics[SkPatchUtils::kLeftP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1)];
- cubics[SkPatchUtils::kRightP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1) + 1];
-
- if ((fModeFlags & kColors_VertexType) && colors) {
- colors[0] = fCornerColors[cornerPos];
- colors[1] = fCornerColors[cornerPos + 1];
- colors[3] = fCornerColors[cornerPos + (fCols + 1)];
- colors[2] = fCornerColors[cornerPos + (fCols + 1) + 1];
- }
-
- if ((fModeFlags & kTexs_VertexType) && texCoords) {
- texCoords[0] = fTexCoords[cornerPos];
- texCoords[1] = fTexCoords[cornerPos + 1];
- texCoords[3] = fTexCoords[cornerPos + (fCols + 1)];
- texCoords[2] = fTexCoords[cornerPos + (fCols + 1) + 1];
- }
-
- return true;
-}
-
-void SkPatchGrid::reset(int rows, int cols, VertexType flags, SkBlendMode blendmode) {
- delete[] fCornerPts;
- delete[] fCornerColors;
- delete[] fTexCoords;
- delete[] fHrzCtrlPts;
- delete[] fVrtCtrlPts;
-
- fCols = cols;
- fRows = rows;
- fModeFlags = flags;
- fBlendMode = blendmode;
-
- fCornerPts = new SkPoint[(fRows + 1) * (fCols + 1)];
- fHrzCtrlPts = new SkPoint[(fRows + 1) * fCols * 2];
- fVrtCtrlPts = new SkPoint[fRows * 2 * (fCols + 1)];
- memset(fCornerPts, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint));
- memset(fHrzCtrlPts, 0, (fRows + 1) * fCols * 2 * sizeof(SkPoint));
- memset(fVrtCtrlPts, 0, fRows * 2 * (fCols + 1) * sizeof(SkPoint));
-
- if (fModeFlags & kColors_VertexType) {
- fCornerColors = new SkColor[(fRows + 1) * (fCols + 1)];
- memset(fCornerColors, 0, (fRows + 1) * (fCols + 1) * sizeof(SkColor));
- }
-
- if (fModeFlags & kTexs_VertexType) {
- fTexCoords = new SkPoint[(fRows + 1) * (fCols + 1)];
- memset(fTexCoords, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint));
- }
-}
-
-void SkPatchGrid::draw(SkCanvas* canvas, SkPaint& paint) {
- int* maxCols = new int[fCols];
- int* maxRows = new int[fRows];
- memset(maxCols, 0, fCols * sizeof(int));
- memset(maxRows, 0, fRows * sizeof(int));
-
- // Get the maximum level of detail per axis for each row and column
- for (int y = 0; y < fRows; y++) {
- for (int x = 0; x < fCols; x++) {
- SkPoint cubics[12];
- this->getPatch(x, y, cubics, nullptr, nullptr);
- SkMatrix matrix = canvas->getTotalMatrix();
- SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix);
- maxCols[x] = SkMax32(maxCols[x], lod.width());
- maxRows[y] = SkMax32(maxRows[y], lod.height());
- }
- }
- // Draw the patches by generating their geometry with the maximum level of detail per axis.
- for (int x = 0; x < fCols; x++) {
- for (int y = 0; y < fRows; y++) {
- SkPoint cubics[12];
- SkPoint texCoords[4];
- SkColor colors[4];
- this->getPatch(x, y, cubics, colors, texCoords);
- SkPatchUtils::VertexData data;
- if (SkPatchUtils::getVertexData(&data, cubics,
- fModeFlags & kColors_VertexType ? colors : nullptr,
- fModeFlags & kTexs_VertexType ? texCoords : nullptr,
- maxCols[x], maxRows[y])) {
- canvas->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount,
- data.fPoints, data.fTexCoords, data.fColors, fBlendMode,
- data.fIndices, data.fIndexCount, paint);
- }
- }
- }
- delete[] maxCols;
- delete[] maxRows;
-}
diff --git a/src/utils/SkPatchGrid.h b/src/utils/SkPatchGrid.h
deleted file mode 100644
index 97a6cb3f01..0000000000
--- a/src/utils/SkPatchGrid.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkPatchGrid_DEFINED
-#define SkPatchGrid_DEFINED
-
-#include "SkCanvas.h"
-#include "SkPatchUtils.h"
-
-/**
- * Class that represents a grid of patches. Adjacent patches share their corners and a color is
- * specified at each one of them. The colors are bilinearly interpolated across the patch.
- *
- * This implementation defines a bidimensional array of patches. There are 3 arrays to store the
- * control points of the patches to avoid storing repeated data since there are several points
- * shared between adjacent patches.
- *
- * The array fCornerPts stores the corner control points of the patches.
- * The array fHrzPts holds the intermidiate control points of the top and bottom curves of a patch.
- * The array fVrtPts holds the intermidiate control points of the left and right curves of a patch.
- * The array fCornerColors holds the corner colors in the same format as fCornerPts.
- * The array fTexCoords holds the texture coordinates in the same format as fCornerpts.
- *
- * fCornerPts fHrzPts fVrtPts
- * -------------- ------------------- --------------
- * | C0 | C1 | C2 | | H0 | H1 | H2 | H3 | | V0 | V1 | V2 |
- * -------------- ------------------ ---------------
- * | C3 | C4 | C5 | | H4 | H5 | H6 | H7 | | V4 | V5 | V6 |
- * -------------- ------------------- --------------
- * | C6 | C7 | C8 | | H8 | H9 | H10| H11| | V6 | V7 | V8 |
- * -------------- ------------------- --------------
- * | V9 | V10| V11|
- * --------------
- *
- * With the above configuration we would have a 2x2 grid of patches:
- * H0 H1 H2 H3
- * / \/ \
- * C0-------C1-------C2
- * /| | |\
- * v0 | v1 | v2
- * v3 | V4 | v5
- * \| | |/
- * C3-H4-H5-C4-H6-H7-C5
- * /| | |\
- * v6 | v7 | v8
- * v9 | v10 | v11
- * \| | |/
- * C6-------C7-------C8
- * \ / \ /
- * H8 H9 H10 H11
- *
- * When trying to get a patch at a certain position it justs builds it with the corresponding
- * points.
- * When adding a patch it tries to add the points at their corresponding position trying to comply
- * with the adjacent points or overwriting them.
- *
- * Based the idea on the SVG2 spec for mesh gradients in which a grid of patches is build as in the
- * the following example:
- * <meshGradient x="100" y="100">
- * <meshRow>
- * <meshPatch>
- * <stop .../>
- * Up to four stops in first patch. See details below.
- * </meshPatch>
- * <meshPatch>
- * Any number of meshPatches in row.
- * </meshPatch>
- * </meshRow>
- * <meshRow>
- * Any number of meshRows, each with the same number of meshPatches as in the first row.
- * </meshRow>
- * </meshGradient>
- */
-class SkPatchGrid {
-
-public:
-
- enum VertexType {
- kNone_VertexType = 0X00,
- kColors_VertexType = 0x01,
- kTexs_VertexType = 0x02,
- kColorsAndTexs_VertexType = 0x03
- };
-
- SkPatchGrid(int rows = 0, int cols = 0, VertexType flags = kNone_VertexType);
-
- ~SkPatchGrid();
-
- /**
- * Add a patch at location (x,y) overwriting the previous patch and shared points so they
- * mantain C0 connectivity.
- * The control points must be passed in a clockwise order starting at the top left corner.
- * The colors and texCoords are the values at the corners of the patch which will be bilerp
- * across it, they must also be in counterclockwise order starting at the top left corner.
- */
- bool setPatch(int x, int y, const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4]);
-
- /**
- * Get patch at location (x,y). If cubics, colors or texCoords is not nullptr it sets patch's
- * array with its corresponding values.
- * The function returns false if the cubics parameter is nullptr or if the (x,y) coordinates are
- * not within the range of the grid.
- */
- bool getPatch(int x, int y, SkPoint cubics[12], SkColor colors[4], SkPoint texCoords[4]) const;
-
- /**
- * Resets the grid of patches to contain rows and cols of patches.
- */
- void reset(int rows, int cols, VertexType flags, SkBlendMode);
-
- /**
- * Draws the grid of patches. The patches are drawn starting at patch (0,0) drawing columns, so
- * for a 2x2 grid the order would be (0,0)->(0,1)->(1,0)->(1,1). The order follows the order
- * of the parametric coordinates of the coons patch.
- */
- void draw(SkCanvas* canvas, SkPaint& paint);
-
- /**
- * Get the dimensions of the grid of patches.
- */
- SkISize getDimensions() const {
- return SkISize::Make(fCols, fRows);
- }
-
-private:
- int fRows, fCols;
- VertexType fModeFlags;
- SkPoint* fCornerPts;
- SkColor* fCornerColors;
- SkPoint* fTexCoords;
- SkPoint* fHrzCtrlPts;
- SkPoint* fVrtCtrlPts;
- SkBlendMode fBlendMode = SkBlendMode::kModulate;
-};
-
-
-#endif
diff --git a/src/utils/SkPatchUtils.cpp b/src/utils/SkPatchUtils.cpp
index cbaae39e8e..52ecfb1ec5 100644
--- a/src/utils/SkPatchUtils.cpp
+++ b/src/utils/SkPatchUtils.cpp
@@ -309,3 +309,149 @@ bool SkPatchUtils::getVertexData(SkPatchUtils::VertexData* data, const SkPoint c
return true;
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+sk_sp<SkVertices> SkPatchUtils::MakeVertices(const SkPoint cubics[12], const SkColor srcColors[4],
+ const SkPoint srcTexCoords[4], int lodX, int lodY) {
+ if (lodX < 1 || lodY < 1 || nullptr == cubics) {
+ return nullptr;
+ }
+
+ // check for overflow in multiplication
+ const int64_t lodX64 = (lodX + 1),
+ lodY64 = (lodY + 1),
+ mult64 = lodX64 * lodY64;
+ if (mult64 > SK_MaxS32) {
+ return nullptr;
+ }
+
+ int vertexCount = SkToS32(mult64);
+ // it is recommended to generate draw calls of no more than 65536 indices, so we never generate
+ // more than 60000 indices. To accomplish that we resize the LOD and vertex count
+ if (vertexCount > 10000 || lodX > 200 || lodY > 200) {
+ float weightX = static_cast<float>(lodX) / (lodX + lodY);
+ float weightY = static_cast<float>(lodY) / (lodX + lodY);
+
+ // 200 comes from the 100 * 2 which is the max value of vertices because of the limit of
+ // 60000 indices ( sqrt(60000 / 6) that comes from data->fIndexCount = lodX * lodY * 6)
+ lodX = static_cast<int>(weightX * 200);
+ lodY = static_cast<int>(weightY * 200);
+ vertexCount = (lodX + 1) * (lodY + 1);
+ }
+ const int indexCount = lodX * lodY * 6;
+ uint32_t flags = 0;
+ if (srcTexCoords) {
+ flags |= SkVertices::kHasTexCoords_BuilderFlag;
+ }
+ if (srcColors) {
+ flags |= SkVertices::kHasColors_BuilderFlag;
+ }
+
+ SkVertices::Builder builder(SkCanvas::kTriangles_VertexMode, vertexCount, indexCount, flags);
+ SkPoint* pos = builder.positions();
+ SkPoint* texs = builder.texCoords();
+ SkColor* colors = builder.colors();
+ uint16_t* indices = builder.indices();
+
+ // if colors is not null then create array for colors
+ SkPMColor colorsPM[kNumCorners];
+ if (srcColors) {
+ // premultiply colors to avoid color bleeding.
+ for (int i = 0; i < kNumCorners; i++) {
+ colorsPM[i] = SkPreMultiplyColor(srcColors[i]);
+ }
+ srcColors = colorsPM;
+ }
+
+ SkPoint pts[kNumPtsCubic];
+ SkPatchUtils::getBottomCubic(cubics, pts);
+ FwDCubicEvaluator fBottom(pts);
+ SkPatchUtils::getTopCubic(cubics, pts);
+ FwDCubicEvaluator fTop(pts);
+ SkPatchUtils::getLeftCubic(cubics, pts);
+ FwDCubicEvaluator fLeft(pts);
+ SkPatchUtils::getRightCubic(cubics, pts);
+ FwDCubicEvaluator fRight(pts);
+
+ fBottom.restart(lodX);
+ fTop.restart(lodX);
+
+ SkScalar u = 0.0f;
+ int stride = lodY + 1;
+ for (int x = 0; x <= lodX; x++) {
+ SkPoint bottom = fBottom.next(), top = fTop.next();
+ fLeft.restart(lodY);
+ fRight.restart(lodY);
+ SkScalar v = 0.f;
+ for (int y = 0; y <= lodY; y++) {
+ int dataIndex = x * (lodY + 1) + y;
+
+ SkPoint left = fLeft.next(), right = fRight.next();
+
+ SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(),
+ (1.0f - v) * top.y() + v * bottom.y());
+ SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(),
+ (1.0f - u) * left.y() + u * right.y());
+ SkPoint s2 = SkPoint::Make(
+ (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].x()
+ + u * fTop.getCtrlPoints()[3].x())
+ + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].x()
+ + u * fBottom.getCtrlPoints()[3].x()),
+ (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].y()
+ + u * fTop.getCtrlPoints()[3].y())
+ + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].y()
+ + u * fBottom.getCtrlPoints()[3].y()));
+ pos[dataIndex] = s0 + s1 - s2;
+
+ if (colors) {
+ uint8_t a = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetA(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetA(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetA(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetA(colorsPM[kBottomRight_Corner]))));
+ uint8_t r = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetR(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetR(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetR(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetR(colorsPM[kBottomRight_Corner]))));
+ uint8_t g = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetG(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetG(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetG(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetG(colorsPM[kBottomRight_Corner]))));
+ uint8_t b = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetB(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetB(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetB(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetB(colorsPM[kBottomRight_Corner]))));
+ colors[dataIndex] = SkPackARGB32(a,r,g,b);
+ }
+
+ if (texs) {
+ texs[dataIndex] = SkPoint::Make(bilerp(u, v, srcTexCoords[kTopLeft_Corner].x(),
+ srcTexCoords[kTopRight_Corner].x(),
+ srcTexCoords[kBottomLeft_Corner].x(),
+ srcTexCoords[kBottomRight_Corner].x()),
+ bilerp(u, v, srcTexCoords[kTopLeft_Corner].y(),
+ srcTexCoords[kTopRight_Corner].y(),
+ srcTexCoords[kBottomLeft_Corner].y(),
+ srcTexCoords[kBottomRight_Corner].y()));
+
+ }
+
+ if(x < lodX && y < lodY) {
+ int i = 6 * (x * lodY + y);
+ indices[i] = x * stride + y;
+ indices[i + 1] = x * stride + 1 + y;
+ indices[i + 2] = (x + 1) * stride + 1 + y;
+ indices[i + 3] = indices[i];
+ indices[i + 4] = indices[i + 2];
+ indices[i + 5] = (x + 1) * stride + y;
+ }
+ v = SkScalarClampMax(v + 1.f / lodY, 1);
+ }
+ u = SkScalarClampMax(u + 1.f / lodX, 1);
+ }
+ return builder.detach();
+}
diff --git a/src/utils/SkPatchUtils.h b/src/utils/SkPatchUtils.h
index 67ab621e8e..c1e8ac1c2f 100644
--- a/src/utils/SkPatchUtils.h
+++ b/src/utils/SkPatchUtils.h
@@ -10,10 +10,12 @@
#include "SkColorPriv.h"
#include "SkMatrix.h"
+#include "SkVertices.h"
class SK_API SkPatchUtils {
public:
+ // DEPRECATED -- use MakeVertices()
/**
* Structure that holds the vertex data related to the tessellation of a patch. It is passed
* as a parameter to the function getVertexData which sets the points, colors and texture
@@ -104,6 +106,7 @@ public:
*/
static void getRightCubic(const SkPoint cubics[12], SkPoint points[4]);
+ // DEPRECATED -- use MakeVertices()
/**
* Function that evaluates the coons patch interpolation.
* data refers to the pointer of the PatchData struct in which the tessellation data is set.
@@ -116,6 +119,9 @@ public:
static bool getVertexData(SkPatchUtils::VertexData* data, const SkPoint cubics[12],
const SkColor colors[4], const SkPoint texCoords[4],
int lodX, int lodY);
+
+ static sk_sp<SkVertices> MakeVertices(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], int lodX, int lodY);
};
#endif