#include "src/gpu/ganesh/ops/GrOvalOpFactory.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkString.h"
#include "include/core/SkStrokeRec.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/private/SkColorData.h"
#include "include/private/base/SkAlignedStorage.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkOnce.h"
#include "include/private/base/SkTArray.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/base/SkArenaAlloc.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkRRectPriv.h"
#include "src/core/SkSLTypeShared.h"
#include "src/gpu/BufferWriter.h"
#include "src/gpu/KeyBuilder.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/ganesh/GrAppliedClip.h"
#include "src/gpu/ganesh/GrBuffer.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrGeometryProcessor.h"
#include "src/gpu/ganesh/GrMeshDrawTarget.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrProcessorAnalysis.h"
#include "src/gpu/ganesh/GrProcessorSet.h"
#include "src/gpu/ganesh/GrProcessorUnitTest.h"
#include "src/gpu/ganesh/GrProgramInfo.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/GrShaderVar.h"
#include "src/gpu/ganesh/GrSimpleMesh.h"
#include "src/gpu/ganesh/GrStyle.h"
#include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
#include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
#include "src/gpu/ganesh/ops/GrMeshDrawOp.h"
#include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
#if defined(GPU_TEST_UTILS)
#include "src/base/SkRandom.h"
#include "src/gpu/ganesh/GrDrawOpTest.h"
#include "src/gpu/ganesh/GrTestUtils.h"
#endif
#include <algorithm>
#include <array>
#include <cstdint>
#include <memory>
#include <utility>
class GrDstProxyView;
class GrGLSLProgramDataManager;
class GrGLSLUniformHandler;
class GrSurfaceProxyView;
enum class GrXferBarrierFlags;
namespace skgpu::ganesh {
class SurfaceDrawContext;
}
usingnamespaceskia_private;
#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
VertexWriter;
VertexColor;
namespace {
static inline bool circle_stays_circle(const SkMatrix& m) { … }
static inline VertexWriter::TriStrip<float> origin_centered_tri_strip(float x, float y) { … }
}
class CircleGeometryProcessor : public GrGeometryProcessor { … };
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(…)
#if defined(GPU_TEST_UTILS)
GrGeometryProcessor* CircleGeometryProcessor::TestCreate(GrProcessorTestData* d) {
bool stroke = d->fRandom->nextBool();
bool roundCaps = stroke ? d->fRandom->nextBool() : false;
bool wideColor = d->fRandom->nextBool();
bool clipPlane = d->fRandom->nextBool();
bool isectPlane = d->fRandom->nextBool();
bool unionPlane = d->fRandom->nextBool();
const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
return CircleGeometryProcessor::Make(d->allocator(), stroke, clipPlane, isectPlane,
unionPlane, roundCaps, wideColor, matrix);
}
#endif
class ButtCapDashedCircleGeometryProcessor : public GrGeometryProcessor { … };
#if defined(GPU_TEST_UTILS)
GrGeometryProcessor* ButtCapDashedCircleGeometryProcessor::TestCreate(GrProcessorTestData* d) {
bool wideColor = d->fRandom->nextBool();
const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
return ButtCapDashedCircleGeometryProcessor::Make(d->allocator(), wideColor, matrix);
}
#endif
class EllipseGeometryProcessor : public GrGeometryProcessor { … };
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(…)
#if defined(GPU_TEST_UTILS)
GrGeometryProcessor* EllipseGeometryProcessor::TestCreate(GrProcessorTestData* d) {
bool stroke = d->fRandom->nextBool();
bool wideColor = d->fRandom->nextBool();
bool useScale = d->fRandom->nextBool();
SkMatrix matrix = GrTest::TestMatrix(d->fRandom);
return EllipseGeometryProcessor::Make(d->allocator(), stroke, wideColor, useScale, matrix);
}
#endif
enum class DIEllipseStyle { … };
class DIEllipseGeometryProcessor : public GrGeometryProcessor { … };
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(…)
#if defined(GPU_TEST_UTILS)
GrGeometryProcessor* DIEllipseGeometryProcessor::TestCreate(GrProcessorTestData* d) {
bool wideColor = d->fRandom->nextBool();
bool useScale = d->fRandom->nextBool();
SkMatrix matrix = GrTest::TestMatrix(d->fRandom);
auto style = (DIEllipseStyle)(d->fRandom->nextRangeU(0, 2));
return DIEllipseGeometryProcessor::Make(d->allocator(), wideColor, useScale, matrix, style);
}
#endif
static const uint16_t gFillCircleIndices[] = …;
static const uint16_t gStrokeCircleIndices[] = …;
static constexpr SkScalar kOctOffset = …;
static constexpr SkPoint kOctagonOuter[] = …;
static constexpr SkScalar kCosPi8 = …;
static constexpr SkScalar kSinPi8 = …;
static constexpr SkPoint kOctagonInner[] = …;
static const int kIndicesPerFillCircle = …;
static const int kIndicesPerStrokeCircle = …;
static const int kVertsPerStrokeCircle = …;
static const int kVertsPerFillCircle = …;
static int circle_type_to_vert_count(bool stroked) { … }
static int circle_type_to_index_count(bool stroked) { … }
static const uint16_t* circle_type_to_indices(bool stroked) { … }
class CircleOp final : public GrMeshDrawOp { … };
class ButtCapDashedCircleOp final : public GrMeshDrawOp { … };
class EllipseOp final : public GrMeshDrawOp { … };
class DIEllipseOp final : public GrMeshDrawOp { … };
static const uint16_t gOverstrokeRRectIndices[] = …;
static const uint16_t* gStandardRRectIndices = …;
static const int kIndicesPerOverstrokeRRect = …;
static const int kIndicesPerFillRRect = …;
static const int kIndicesPerStrokeRRect = …;
static const int kVertsPerStandardRRect = …;
static const int kVertsPerOverstrokeRRect = …;
enum RRectType { … };
static int rrect_type_to_vert_count(RRectType type) { … }
static int rrect_type_to_index_count(RRectType type) { … }
static const uint16_t* rrect_type_to_indices(RRectType type) { … }
class CircularRRectOp final : public GrMeshDrawOp { … };
static const int kNumRRectsInIndexBuffer = …;
SKGPU_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey);
SKGPU_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey);
static sk_sp<const GrBuffer> get_rrect_index_buffer(RRectType type,
GrResourceProvider* resourceProvider) { … }
class EllipticalRRectOp final : public GrMeshDrawOp { … };
GrOp::Owner GrOvalOpFactory::MakeCircularRRectOp(GrRecordingContext* context,
GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkRRect& rrect,
const SkStrokeRec& stroke,
const GrShaderCaps* shaderCaps) { … }
GrOp::Owner make_rrect_op(GrRecordingContext* context,
GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkRRect& rrect,
const SkStrokeRec& stroke) { … }
GrOp::Owner GrOvalOpFactory::MakeRRectOp(GrRecordingContext* context,
GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkRRect& rrect,
const SkStrokeRec& stroke,
const GrShaderCaps* shaderCaps) { … }
GrOp::Owner GrOvalOpFactory::MakeCircleOp(GrRecordingContext* context,
GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkRect& oval,
const GrStyle& style,
const GrShaderCaps* shaderCaps) { … }
GrOp::Owner GrOvalOpFactory::MakeOvalOp(GrRecordingContext* context,
GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkRect& oval,
const GrStyle& style,
const GrShaderCaps* shaderCaps) { … }
GrOp::Owner GrOvalOpFactory::MakeArcOp(GrRecordingContext* context,
GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkRect& oval, SkScalar startAngle,
SkScalar sweepAngle, bool useCenter,
const GrStyle& style,
const GrShaderCaps* shaderCaps) { … }
#if defined(GPU_TEST_UTILS)
GR_DRAW_OP_TEST_DEFINE(CircleOp) {
if (numSamples > 1) {
return nullptr;
}
do {
SkScalar rotate = random->nextSScalar1() * 360.f;
SkScalar translateX = random->nextSScalar1() * 1000.f;
SkScalar translateY = random->nextSScalar1() * 1000.f;
SkScalar scale;
do {
scale = random->nextSScalar1() * 100.f;
} while (scale == 0);
SkMatrix viewMatrix;
viewMatrix.setRotate(rotate);
viewMatrix.postTranslate(translateX, translateY);
viewMatrix.postScale(scale, scale);
SkRect circle = GrTest::TestSquare(random);
SkPoint center = {circle.centerX(), circle.centerY()};
SkScalar radius = circle.width() / 2.f;
SkStrokeRec stroke = GrTest::TestStrokeRec(random);
CircleOp::ArcParams arcParamsTmp;
const CircleOp::ArcParams* arcParams = nullptr;
if (random->nextBool()) {
arcParamsTmp.fStartAngleRadians = random->nextSScalar1() * SK_ScalarPI * 2;
arcParamsTmp.fSweepAngleRadians = random->nextSScalar1() * SK_ScalarPI * 2 - .01f;
arcParamsTmp.fUseCenter = random->nextBool();
arcParams = &arcParamsTmp;
}
GrOp::Owner op = CircleOp::Make(context, std::move(paint), viewMatrix,
center, radius,
GrStyle(stroke, nullptr), arcParams);
if (op) {
return op;
}
assert_alive(paint);
} while (true);
}
GR_DRAW_OP_TEST_DEFINE(ButtCapDashedCircleOp) {
if (numSamples > 1) {
return nullptr;
}
SkScalar rotate = random->nextSScalar1() * 360.f;
SkScalar translateX = random->nextSScalar1() * 1000.f;
SkScalar translateY = random->nextSScalar1() * 1000.f;
SkScalar scale;
do {
scale = random->nextSScalar1() * 100.f;
} while (scale == 0);
SkMatrix viewMatrix;
viewMatrix.setRotate(rotate);
viewMatrix.postTranslate(translateX, translateY);
viewMatrix.postScale(scale, scale);
SkRect circle = GrTest::TestSquare(random);
SkPoint center = {circle.centerX(), circle.centerY()};
SkScalar radius = circle.width() / 2.f;
SkScalar strokeWidth = random->nextRangeScalar(0.001f * radius, 1.8f * radius);
SkScalar onAngle = random->nextRangeScalar(0.01f, 1000.f);
SkScalar offAngle = random->nextRangeScalar(0.01f, 1000.f);
SkScalar startAngle = random->nextRangeScalar(-1000.f, 1000.f);
SkScalar phase = random->nextRangeScalar(-1000.f, 1000.f);
return ButtCapDashedCircleOp::Make(context, std::move(paint), viewMatrix,
center, radius, strokeWidth,
startAngle, onAngle, offAngle, phase);
}
GR_DRAW_OP_TEST_DEFINE(EllipseOp) {
SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
SkRect ellipse = GrTest::TestSquare(random);
return EllipseOp::Make(context, std::move(paint), viewMatrix, ellipse,
GrTest::TestStrokeRec(random));
}
GR_DRAW_OP_TEST_DEFINE(DIEllipseOp) {
SkMatrix viewMatrix = GrTest::TestMatrix(random);
SkRect ellipse = GrTest::TestSquare(random);
return DIEllipseOp::Make(context, std::move(paint), viewMatrix, ellipse,
GrTest::TestStrokeRec(random));
}
GR_DRAW_OP_TEST_DEFINE(CircularRRectOp) {
do {
SkScalar rotate = random->nextSScalar1() * 360.f;
SkScalar translateX = random->nextSScalar1() * 1000.f;
SkScalar translateY = random->nextSScalar1() * 1000.f;
SkScalar scale;
do {
scale = random->nextSScalar1() * 100.f;
} while (scale == 0);
SkMatrix viewMatrix;
viewMatrix.setRotate(rotate);
viewMatrix.postTranslate(translateX, translateY);
viewMatrix.postScale(scale, scale);
SkRect rect = GrTest::TestRect(random);
SkScalar radius = random->nextRangeF(0.1f, 10.f);
SkRRect rrect = SkRRect::MakeRectXY(rect, radius, radius);
if (rrect.isOval()) {
continue;
}
GrOp::Owner op =
GrOvalOpFactory::MakeCircularRRectOp(context, std::move(paint), viewMatrix, rrect,
GrTest::TestStrokeRec(random), nullptr);
if (op) {
return op;
}
assert_alive(paint);
} while (true);
}
GR_DRAW_OP_TEST_DEFINE(RRectOp) {
SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
const SkRRect& rrect = GrTest::TestRRectSimple(random);
return make_rrect_op(context, std::move(paint), viewMatrix, rrect,
GrTest::TestStrokeRec(random));
}
#endif
#endif