7d954ad797
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4020 CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot Change-Id: I19cd056f2af778f10e8c6c2b7b2735593b43dbac Reviewed-on: https://skia-review.googlesource.com/4020 Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Mike Reed <reed@google.com>
190 lines
7.6 KiB
C++
190 lines
7.6 KiB
C++
/*
|
|
* 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;
|
|
}
|