2020-06-16 21:56:16 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2020 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gm/gm.h"
|
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkPath.h"
|
|
|
|
#include "include/core/SkPoint.h"
|
2020-09-17 18:16:54 +00:00
|
|
|
#include "include/gpu/GrContextOptions.h"
|
2021-06-03 14:14:16 +00:00
|
|
|
#include "include/gpu/GrDirectContext.h"
|
2021-07-23 21:33:09 +00:00
|
|
|
#include "include/utils/SkRandom.h"
|
2021-07-20 13:27:00 +00:00
|
|
|
#include "src/gpu/GrCaps.h"
|
2021-06-03 14:14:16 +00:00
|
|
|
#include "src/gpu/GrDirectContextPriv.h"
|
2020-09-17 18:16:54 +00:00
|
|
|
#include "src/gpu/GrDrawingManager.h"
|
2021-07-20 13:27:00 +00:00
|
|
|
#include "src/gpu/GrRecordingContextPriv.h"
|
2021-08-19 18:57:05 +00:00
|
|
|
#include "src/gpu/ops/TessellationPathRenderer.h"
|
2020-06-16 21:56:16 +00:00
|
|
|
|
|
|
|
static constexpr float kStrokeWidth = 100;
|
2020-09-17 18:16:54 +00:00
|
|
|
static constexpr int kTestWidth = 120 * 4;
|
|
|
|
static constexpr int kTestHeight = 120 * 3 + 140;
|
|
|
|
|
2021-05-11 18:36:51 +00:00
|
|
|
static void draw_strokes(SkCanvas* canvas, SkRandom* rand, const SkPath& path,
|
2020-09-17 18:16:54 +00:00
|
|
|
const SkPath& cubic) {
|
|
|
|
SkPaint strokePaint;
|
|
|
|
strokePaint.setAntiAlias(true);
|
|
|
|
strokePaint.setStrokeWidth(kStrokeWidth);
|
|
|
|
strokePaint.setStyle(SkPaint::kStroke_Style);
|
|
|
|
|
|
|
|
SkAutoCanvasRestore arc(canvas, true);
|
|
|
|
strokePaint.setStrokeJoin(SkPaint::kBevel_Join);
|
2021-05-11 18:36:51 +00:00
|
|
|
strokePaint.setColor(rand->nextU() | 0xff808080);
|
2020-09-17 18:16:54 +00:00
|
|
|
canvas->drawPath(path, strokePaint);
|
|
|
|
|
|
|
|
canvas->translate(120, 0);
|
|
|
|
strokePaint.setStrokeJoin(SkPaint::kRound_Join);
|
2021-05-11 18:36:51 +00:00
|
|
|
strokePaint.setColor(rand->nextU() | 0xff808080);
|
2020-09-17 18:16:54 +00:00
|
|
|
canvas->drawPath(path, strokePaint);
|
|
|
|
|
|
|
|
canvas->translate(120, 0);
|
|
|
|
strokePaint.setStrokeJoin(SkPaint::kMiter_Join);
|
2021-05-11 18:36:51 +00:00
|
|
|
strokePaint.setColor(rand->nextU() | 0xff808080);
|
2020-09-17 18:16:54 +00:00
|
|
|
canvas->drawPath(path, strokePaint);
|
|
|
|
|
|
|
|
canvas->translate(120, 0);
|
2021-05-11 18:36:51 +00:00
|
|
|
strokePaint.setColor(rand->nextU() | 0xff808080);
|
2020-09-17 18:16:54 +00:00
|
|
|
canvas->drawPath(cubic, strokePaint);
|
|
|
|
}
|
|
|
|
|
2021-05-11 18:36:51 +00:00
|
|
|
static void draw_test(SkCanvas* canvas) {
|
|
|
|
SkRandom rand;
|
|
|
|
|
|
|
|
if (canvas->recordingContext() &&
|
|
|
|
canvas->recordingContext()->priv().caps()->shaderCaps()->tessellationSupport() &&
|
2021-05-26 05:49:39 +00:00
|
|
|
canvas->recordingContext()->priv().caps()->shaderCaps()->maxTessellationSegments() == 5) {
|
|
|
|
// The caller successfully overrode the max tessellation segments to 5. Indicate this in the
|
|
|
|
// background color.
|
2021-05-11 18:36:51 +00:00
|
|
|
canvas->clear(SkColorSetARGB(255, 64, 0, 0));
|
|
|
|
} else {
|
|
|
|
canvas->clear(SK_ColorBLACK);
|
|
|
|
}
|
|
|
|
|
2020-09-17 18:16:54 +00:00
|
|
|
SkAutoCanvasRestore arc(canvas, true);
|
|
|
|
canvas->translate(60, 60);
|
|
|
|
|
2021-05-11 18:36:51 +00:00
|
|
|
draw_strokes(canvas, &rand,
|
2020-09-17 18:16:54 +00:00
|
|
|
SkPath().lineTo(10,0).lineTo(10,10),
|
|
|
|
SkPath().cubicTo(10,0, 10,0, 10,10));
|
|
|
|
canvas->translate(0, 120);
|
|
|
|
|
2021-05-11 18:36:51 +00:00
|
|
|
draw_strokes(canvas, &rand,
|
2020-09-17 18:16:54 +00:00
|
|
|
SkPath().lineTo(0,-10).lineTo(0,10),
|
|
|
|
SkPath().cubicTo(0,-10, 0,-10, 0,10));
|
|
|
|
canvas->translate(0, 120);
|
|
|
|
|
2021-05-11 18:36:51 +00:00
|
|
|
draw_strokes(canvas, &rand,
|
2020-09-17 18:16:54 +00:00
|
|
|
SkPath().lineTo(0,-10).lineTo(10,-10).lineTo(10,10).lineTo(0,10),
|
|
|
|
SkPath().cubicTo(0,-10, 10,10, 0,10));
|
|
|
|
canvas->translate(0, 140);
|
|
|
|
|
2021-05-11 18:36:51 +00:00
|
|
|
draw_strokes(canvas, &rand,
|
2020-09-17 18:16:54 +00:00
|
|
|
SkPath().lineTo(0,-10).lineTo(10,-10).lineTo(10,0).lineTo(0,0),
|
|
|
|
SkPath().cubicTo(0,-10, 10,0, 0,0));
|
|
|
|
canvas->translate(0, 120);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_SIMPLE_GM(widebuttcaps, canvas, kTestWidth, kTestHeight) {
|
2021-05-11 18:36:51 +00:00
|
|
|
canvas->clear(SK_ColorBLACK);
|
|
|
|
draw_test(canvas);
|
2020-09-17 18:16:54 +00:00
|
|
|
}
|
|
|
|
|
2021-06-03 14:14:16 +00:00
|
|
|
class WideButtCaps_tess_segs_5 : public skiagm::GM {
|
2020-06-16 21:56:16 +00:00
|
|
|
SkString onShortName() override {
|
2020-09-17 18:16:54 +00:00
|
|
|
return SkString("widebuttcaps_tess_segs_5");
|
2020-06-16 21:56:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SkISize onISize() override {
|
2020-09-17 18:16:54 +00:00
|
|
|
return SkISize::Make(kTestWidth, kTestHeight);
|
2020-06-16 21:56:16 +00:00
|
|
|
}
|
|
|
|
|
2020-09-22 22:47:52 +00:00
|
|
|
// Pick a very small, odd (and better yet, prime) number of segments.
|
|
|
|
//
|
|
|
|
// - Odd because it makes the tessellation strip asymmetric, which will be important to test for
|
|
|
|
// future plans that involve drawing in reverse order.
|
|
|
|
//
|
|
|
|
// - >=4 because the tessellator code will just assume we have enough to combine a miter join
|
|
|
|
// and line in a single patch. (Requires 4 segments. Spec required minimum is 64.)
|
2021-10-08 22:48:26 +00:00
|
|
|
inline static constexpr int kMaxTessellationSegmentsOverride = 5;
|
2020-09-22 22:47:52 +00:00
|
|
|
|
2020-09-17 18:16:54 +00:00
|
|
|
void modifyGrContextOptions(GrContextOptions* options) override {
|
2020-09-22 22:47:52 +00:00
|
|
|
options->fMaxTessellationSegmentsOverride = kMaxTessellationSegmentsOverride;
|
2021-05-25 16:11:46 +00:00
|
|
|
options->fAlwaysPreferHardwareTessellation = true;
|
2020-09-17 18:16:54 +00:00
|
|
|
// Only allow the tessellation path renderer.
|
|
|
|
options->fGpuPathRenderers = (GpuPathRenderers)((int)options->fGpuPathRenderers &
|
|
|
|
(int)GpuPathRenderers::kTessellation);
|
2020-06-16 21:56:16 +00:00
|
|
|
}
|
|
|
|
|
2021-06-03 14:14:16 +00:00
|
|
|
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
|
|
|
|
auto dContext = GrAsDirectContext(canvas->recordingContext());
|
|
|
|
if (!dContext) {
|
|
|
|
*errorMsg = "GM relies on having access to a live direct context.";
|
|
|
|
return DrawResult::kSkip;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dContext->priv().caps()->shaderCaps()->tessellationSupport() ||
|
2021-08-19 21:04:05 +00:00
|
|
|
!skgpu::v1::TessellationPathRenderer::IsSupported(*dContext->priv().caps())) {
|
2020-09-17 18:16:54 +00:00
|
|
|
errorMsg->set("Tessellation not supported.");
|
|
|
|
return DrawResult::kSkip;
|
|
|
|
}
|
2021-06-03 14:14:16 +00:00
|
|
|
auto opts = dContext->priv().drawingManager()->testingOnly_getOptionsForPathRendererChain();
|
2020-09-17 18:16:54 +00:00
|
|
|
if (!(opts.fGpuPathRenderers & GpuPathRenderers::kTessellation)) {
|
2021-08-19 21:04:05 +00:00
|
|
|
errorMsg->set("TessellationPathRenderer disabled.");
|
2020-09-17 18:16:54 +00:00
|
|
|
return DrawResult::kSkip;
|
|
|
|
}
|
2021-06-03 14:14:16 +00:00
|
|
|
if (dContext->priv().caps()->shaderCaps()->maxTessellationSegments() !=
|
2020-09-22 22:47:52 +00:00
|
|
|
kMaxTessellationSegmentsOverride) {
|
|
|
|
errorMsg->set("modifyGrContextOptions() did not limit maxTessellationSegments. "
|
|
|
|
"(Are you running viewer? If so use '--maxTessellationSegments 5'.)");
|
|
|
|
return DrawResult::kFail;
|
|
|
|
}
|
2020-09-17 18:16:54 +00:00
|
|
|
// Suppress a tessellator warning message that caps.maxTessellationSegments is too small.
|
2021-06-03 14:14:16 +00:00
|
|
|
GrRecordingContextPriv::AutoSuppressWarningMessages aswm(dContext);
|
2021-05-11 18:36:51 +00:00
|
|
|
draw_test(canvas);
|
2020-09-17 18:16:54 +00:00
|
|
|
return DrawResult::kOk;
|
2020-06-16 21:56:16 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-17 18:16:54 +00:00
|
|
|
DEF_GM( return new WideButtCaps_tess_segs_5; )
|