skia2/gm/crbug_224618.cpp

119 lines
4.4 KiB
C++
Raw Normal View History

/*
* Copyright 2020 Google LLC
*
* 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/SkColor.h"
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
#include "include/core/SkImage.h"
#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
#include "include/core/SkSurface.h"
#include "include/effects/SkGradientShader.h"
#include "tools/timer/TimeUtils.h"
// Adapted from https://codepen.io/adamdupuis/pen/qLYzqB
class CrBug224618GM : public skiagm::GM {
public:
CrBug224618GM() : fTime(0.f) {}
protected:
SkString onShortName() override {
return SkString("crbug_224618");
}
SkISize onISize() override {
return SkISize::Make(kMaxVW, kMaxVW);
}
// This animates the FOV in viewer, to ensure the panorama covering rects are stable across
// a variety of perspective matrices
bool onAnimate(double nanos) override {
fTime = TimeUtils::Scaled(1e-9f * nanos, 0.5f);
return true;
}
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
void onOnceBeforeDraw() override {
static const SkColor kColors[2] = {SK_ColorTRANSPARENT, SkColorSetARGB(128, 255, 255, 255)};
sk_sp<SkShader> gradient = SkGradientShader::MakeRadial(
{200.f, 200.f}, 25.f, kColors, nullptr, 2, SkTileMode::kMirror,
SkGradientShader::kInterpolateColorsInPremul_Flag, nullptr);
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(400, 400);
SkPaint bgPaint;
bgPaint.setShader(gradient);
surface->getCanvas()->drawPaint(bgPaint);
fCubeImage = surface->makeImageSnapshot();
}
void onDraw(SkCanvas* canvas) override {
SkScalar viewportWidth = SkScalarMod(fTime, 10.f) / 10.f * (kMaxVW - kMinVW) + kMinVW;
SkScalar radius = viewportWidth / 2.f; // round?
// See https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective
SkM44 proj{1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, -1.f / radius, 1.f};
SkM44 zoom = SkM44::Translate(0.f, 0.f, radius);
SkM44 postZoom = SkM44::Translate(0.f, 0.f, -radius - 1.f);
SkM44 rotateHorizontal = SkM44::Rotate({0, 1, 0}, 2.356194490192345f);
// w in degrees will need to be converted to radians
SkV4 axisAngles[6] = {
{0.f, 1.f, 0.f, -90.f}, // rotateY(-90deg)
{1.f, 0.f, 0.f, 0.f}, // <none>
{0.f, 1.f, 0.f, 90.f}, // rotateY(90deg)
{0.f, 1.f, 0.f, 180.f}, // rotateY(180deg)
{1.f, 0.f, 0.f, -90.f}, // rotateX(-90deg)
{1.f, 0.f, 0.f, 90.f}, // rotateX(90deg)
};
SkColor faceColors[6] = {
SK_ColorRED,
SK_ColorGREEN,
SK_ColorBLUE,
SK_ColorYELLOW,
SkColorSetARGB(0xFF, 0xFF, 0xA5, 0x00), // orange css
SkColorSetARGB(0xFF, 0x80, 0x00, 0x80) // purple css
};
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
for (int i = 0; i < 6; ++i) {
SkM44 model = SkM44::Rotate({axisAngles[i].x, axisAngles[i].y, axisAngles[i].z},
SkDegreesToRadians(axisAngles[i].w));
model = SkM44::Translate(radius, radius) * proj * // project and place content
zoom * rotateHorizontal * model * postZoom * // main model matrix
SkM44::Translate(-radius, -radius); // center content
canvas->save();
canvas->concat44(model);
SkPaint fillPaint;
fillPaint.setAntiAlias(true);
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
fillPaint.setFilterQuality(kLow_SkFilterQuality);
fillPaint.setColor(faceColors[i]);
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
// Leverages GrFillRectOp on GPU backend
canvas->drawRect(SkRect::MakeWH(viewportWidth, viewportWidth), fillPaint);
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
// Leverages GrTextureOp on GPU backend, to ensure sure both quad paths handle clipping
canvas->drawImageRect(fCubeImage.get(),
SkRect::MakeWH(fCubeImage->width(), fCubeImage->height()),
SkRect::MakeWH(viewportWidth, viewportWidth), &fillPaint,
SkCanvas::kFast_SrcRectConstraint);
canvas->restore();
}
}
private:
static const int kMaxVW = 800;
static const int kMinVW = 300;
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
SkScalar fTime;
Add ClipToW0 utility function for GrQuads, and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-02-07 15:14:45 +00:00
sk_sp<SkImage> fCubeImage;
};
DEF_GM(return new CrBug224618GM();)