2020-01-22 19:32:11 +00:00
|
|
|
/*
|
|
|
|
* 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"
|
2020-01-22 19:32:11 +00:00
|
|
|
#include "include/core/SkMatrix.h"
|
2020-01-26 01:37:15 +00:00
|
|
|
#include "include/core/SkMatrix44.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"
|
2020-01-22 19:32:11 +00:00
|
|
|
#include "include/private/SkM44.h"
|
|
|
|
#include "tools/timer/TimeUtils.h"
|
|
|
|
|
2020-01-26 01:37:15 +00:00
|
|
|
static SkM44 rotate_axis_angle(SkScalar x, SkScalar y, SkScalar z, SkScalar radians) {
|
|
|
|
// SkM44 doesn't expose any rotation factories yet
|
|
|
|
SkMatrix44 m;
|
|
|
|
m.setRotateAboutUnit(x, y, z, radians);
|
|
|
|
|
|
|
|
float a[16];
|
|
|
|
m.asColMajorf(a);
|
|
|
|
SkM44 m4;
|
|
|
|
m4.setColMajor(a);
|
|
|
|
return m4;
|
|
|
|
}
|
|
|
|
|
2020-01-22 19:32:11 +00:00
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
2020-01-22 19:32:11 +00:00
|
|
|
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);
|
2020-01-26 01:37:15 +00:00
|
|
|
SkM44 rotateHorizontal = rotate_axis_angle(0.f, 1.f, 0.f, 2.356194490192345f);
|
2020-01-22 19:32:11 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
2020-01-22 19:32:11 +00:00
|
|
|
for (int i = 0; i < 6; ++i) {
|
2020-01-26 01:37:15 +00:00
|
|
|
SkM44 model = rotate_axis_angle(axisAngles[i].x, axisAngles[i].y, axisAngles[i].z,
|
2020-01-22 19:32:11 +00:00
|
|
|
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->experimental_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);
|
2020-01-22 19:32:11 +00:00
|
|
|
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
|
2020-01-22 19:32:11 +00:00
|
|
|
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);
|
|
|
|
|
2020-01-22 19:32:11 +00:00
|
|
|
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
|
|
|
|
2020-01-22 19:32:11 +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;
|
2020-01-22 19:32:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
DEF_GM(return new CrBug224618GM();)
|