forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rework raster cache to fix numerous issues. (flutter#3717)
* Fix pixel rounding error in the picture layer by first ensuring that the texture for the image is at least as big as the next integer size along each dimension and using kStrict_SrcRectConstraint while drawing the same image. We already select the source subset by looking at the cull rect of the picture. * Decompose the transformation matrix into a series of operations that generated the same to calculate the scale at which to rasterize the picture. This make the rasterization scale resilient to transformations that introduce a perspective component to the resultant matrix. * The scale in the decomposed matrix is now part of the key in the cache. * Raster cache images that could never be rasterized were still taking part in the cache. Now, those entries are rejected early on. This leads to the sweep after the frame iterating over fewer items. * Added a unit test target.
- Loading branch information
1 parent
c3721a5
commit 1c6a531
Showing
15 changed files
with
735 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright 2017 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/flow/debug_print.h" | ||
|
||
#include <ostream> | ||
|
||
#include "third_party/skia/include/core/SkString.h" | ||
|
||
std::ostream& operator<<(std::ostream& os, const flow::MatrixDecomposition& m) { | ||
if (!m.IsValid()) { | ||
os << "Invalid Matrix!" << std::endl; | ||
return os; | ||
} | ||
|
||
os << "Translation (x, y, z): " << m.translation() << std::endl; | ||
os << "Scale (z, y, z): " << m.scale() << std::endl; | ||
os << "Shear (zy, yz, zx): " << m.shear() << std::endl; | ||
os << "Perspective (x, y, z, w): " << m.perspective() << std::endl; | ||
os << "Rotation (x, y, z, w): " << m.rotation() << std::endl; | ||
|
||
return os; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& os, const SkMatrix& m) { | ||
SkString string; | ||
m.toString(&string); | ||
os << string.c_str(); | ||
return os; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& os, const SkMatrix44& m) { | ||
os << m.get(0, 0) << ", " << m.get(0, 1) << ", " << m.get(0, 2) << ", " | ||
<< m.get(0, 3) << std::endl; | ||
os << m.get(1, 0) << ", " << m.get(1, 1) << ", " << m.get(1, 2) << ", " | ||
<< m.get(1, 3) << std::endl; | ||
os << m.get(2, 0) << ", " << m.get(2, 1) << ", " << m.get(2, 2) << ", " | ||
<< m.get(2, 3) << std::endl; | ||
os << m.get(3, 0) << ", " << m.get(3, 1) << ", " << m.get(3, 2) << ", " | ||
<< m.get(3, 3); | ||
return os; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& os, const SkVector3& v) { | ||
os << v.x() << ", " << v.y() << ", " << v.z(); | ||
return os; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& os, const SkVector4& v) { | ||
os << v.fData[0] << ", " << v.fData[1] << ", " << v.fData[2] << ", " | ||
<< v.fData[3]; | ||
return os; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& os, const flow::RasterCacheKey& k) { | ||
os << "Picture: " << k.picture_id() << " Scale: " << k.scale_key().width() | ||
<< ", " << k.scale_key().height(); | ||
return os; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright 2017 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_FLOW_DEBUG_PRINT_H_ | ||
#define FLUTTER_FLOW_DEBUG_PRINT_H_ | ||
|
||
#include "flutter/flow/matrix_decomposition.h" | ||
#include "flutter/flow/raster_cache_key.h" | ||
#include "lib/ftl/macros.h" | ||
#include "third_party/skia/include/core/SkMatrix.h" | ||
#include "third_party/skia/include/core/SkMatrix44.h" | ||
#include "third_party/skia/include/core/SkPoint3.h" | ||
|
||
#define DEF_PRINTER(x) std::ostream& operator<<(std::ostream&, const x&); | ||
|
||
DEF_PRINTER(flow::RasterCacheKey); | ||
DEF_PRINTER(flow::MatrixDecomposition); | ||
DEF_PRINTER(SkMatrix); | ||
DEF_PRINTER(SkMatrix44); | ||
DEF_PRINTER(SkVector3); | ||
DEF_PRINTER(SkVector4); | ||
|
||
#endif // FLUTTER_FLOW_DEBUG_PRINT_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// Copyright 2017 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/flow/matrix_decomposition.h" | ||
|
||
namespace flow { | ||
|
||
static inline SkVector3 SkVector3Combine(const SkVector3& a, | ||
float a_scale, | ||
const SkVector3& b, | ||
float b_scale) { | ||
return { | ||
a_scale * a.fX + b_scale * b.fX, // | ||
a_scale * a.fY + b_scale * b.fY, // | ||
a_scale * a.fZ + b_scale * b.fZ, // | ||
}; | ||
} | ||
|
||
static inline SkVector3 SkVector3Cross(const SkVector3& a, const SkVector3& b) { | ||
return { | ||
(a.fY * b.fZ) - (a.fZ * b.fY), // | ||
(a.fZ * b.fX) - (a.fX * b.fZ), // | ||
(a.fX * b.fY) - (a.fY * b.fX) // | ||
}; | ||
} | ||
|
||
MatrixDecomposition::MatrixDecomposition(const SkMatrix& matrix) | ||
: MatrixDecomposition(SkMatrix44{matrix}) {} | ||
|
||
MatrixDecomposition::MatrixDecomposition(SkMatrix44 matrix) : valid_(false) { | ||
if (matrix.get(3, 3) == 0) { | ||
return; | ||
} | ||
|
||
for (int i = 0; i < 4; i++) { | ||
for (int j = 0; j < 4; j++) { | ||
matrix.set(j, i, matrix.get(j, i) / matrix.get(3, 3)); | ||
} | ||
} | ||
|
||
SkMatrix44 perpective_matrix = matrix; | ||
for (int i = 0; i < 3; i++) { | ||
perpective_matrix.set(3, i, 0.0); | ||
} | ||
|
||
perpective_matrix.set(3, 3, 1.0); | ||
|
||
if (perpective_matrix.determinant() == 0.0) { | ||
return; | ||
} | ||
|
||
if (matrix.get(3, 0) != 0.0 || matrix.get(3, 1) != 0.0 || | ||
matrix.get(3, 2) != 0.0) { | ||
const SkVector4 right_hand_side(matrix.get(3, 0), matrix.get(3, 1), | ||
matrix.get(3, 2), matrix.get(3, 3)); | ||
|
||
SkMatrix44 inverted_transposed( | ||
SkMatrix44::Uninitialized_Constructor::kUninitialized_Constructor); | ||
if (!perpective_matrix.invert(&inverted_transposed)) { | ||
return; | ||
} | ||
inverted_transposed.transpose(); | ||
|
||
perspective_ = inverted_transposed * right_hand_side; | ||
|
||
matrix.set(3, 0, 0); | ||
matrix.set(3, 1, 0); | ||
matrix.set(3, 2, 0); | ||
matrix.set(3, 3, 1); | ||
} | ||
|
||
translation_ = {matrix.get(0, 3), matrix.get(1, 3), matrix.get(2, 3)}; | ||
|
||
matrix.set(0, 3, 0.0); | ||
matrix.set(1, 3, 0.0); | ||
matrix.set(2, 3, 0.0); | ||
|
||
SkVector3 row[3]; | ||
for (int i = 0; i < 3; i++) { | ||
row[i].set(matrix.get(0, i), matrix.get(1, i), matrix.get(2, i)); | ||
} | ||
|
||
scale_.fX = row[0].length(); | ||
row[0].normalize(); | ||
|
||
shear_.fX = row[0].dot(row[1]); | ||
row[1] = SkVector3Combine(row[1], 1.0, row[0], -shear_.fX); | ||
|
||
scale_.fY = row[1].length(); | ||
row[1].normalize(); | ||
shear_.fX /= scale_.fY; | ||
|
||
shear_.fY = row[0].dot(row[2]); | ||
row[2] = SkVector3Combine(row[2], 1.0, row[0], -shear_.fY); | ||
shear_.fZ = row[1].dot(row[2]); | ||
row[2] = SkVector3Combine(row[2], 1.0, row[1], -shear_.fZ); | ||
|
||
scale_.fZ = row[2].length(); | ||
row[2].normalize(); | ||
|
||
shear_.fY /= scale_.fZ; | ||
shear_.fZ /= scale_.fZ; | ||
|
||
if (row[0].dot(SkVector3Cross(row[1], row[2])) < 0) { | ||
scale_.fX *= -1; | ||
scale_.fY *= -1; | ||
scale_.fZ *= -1; | ||
|
||
for (int i = 0; i < 3; i++) { | ||
row[i].fX *= -1; | ||
row[i].fY *= -1; | ||
row[i].fZ *= -1; | ||
} | ||
} | ||
|
||
rotation_.set(0.5 * sqrt(fmax(1.0 + row[0].fX - row[1].fY - row[2].fZ, 0.0)), | ||
0.5 * sqrt(fmax(1.0 - row[0].fX + row[1].fY - row[2].fZ, 0.0)), | ||
0.5 * sqrt(fmax(1.0 - row[0].fX - row[1].fY + row[2].fZ, 0.0)), | ||
0.5 * sqrt(fmax(1.0 + row[0].fX + row[1].fY + row[2].fZ, 0.0))); | ||
|
||
if (row[2].fY > row[1].fZ) { | ||
rotation_.fData[0] = -rotation_.fData[0]; | ||
} | ||
if (row[0].fZ > row[2].fX) { | ||
rotation_.fData[1] = -rotation_.fData[1]; | ||
} | ||
if (row[1].fX > row[0].fY) { | ||
rotation_.fData[2] = -rotation_.fData[2]; | ||
} | ||
|
||
valid_ = true; | ||
} | ||
|
||
MatrixDecomposition::~MatrixDecomposition() = default; | ||
|
||
bool MatrixDecomposition::IsValid() const { | ||
return valid_; | ||
} | ||
|
||
} // namespace flow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright 2017 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_FLOW_MATRIX_DECOMPOSITION_H_ | ||
#define FLUTTER_FLOW_MATRIX_DECOMPOSITION_H_ | ||
|
||
#include "lib/ftl/macros.h" | ||
#include "third_party/skia/include/core/SkMatrix.h" | ||
#include "third_party/skia/include/core/SkMatrix44.h" | ||
#include "third_party/skia/include/core/SkPoint3.h" | ||
|
||
namespace flow { | ||
|
||
/// Decomposes a given non-degenerate transformation matrix into a sequence of | ||
/// operations that produced it. The validity of the decomposition must always | ||
/// be checked before attempting to access any of the decomposed elements. | ||
class MatrixDecomposition { | ||
public: | ||
MatrixDecomposition(const SkMatrix& matrix); | ||
|
||
MatrixDecomposition(SkMatrix44 matrix); | ||
|
||
~MatrixDecomposition(); | ||
|
||
bool IsValid() const; | ||
|
||
const SkVector3& translation() const { return translation_; } | ||
|
||
const SkVector3& scale() const { return scale_; } | ||
|
||
const SkVector3& shear() const { return shear_; } | ||
|
||
const SkVector4& perspective() const { return perspective_; } | ||
|
||
const SkVector4& rotation() const { return rotation_; } | ||
|
||
private: | ||
bool valid_; | ||
SkVector3 translation_; | ||
SkVector3 scale_; | ||
SkVector3 shear_; | ||
SkVector4 perspective_; | ||
SkVector4 rotation_; | ||
|
||
FTL_DISALLOW_COPY_AND_ASSIGN(MatrixDecomposition); | ||
}; | ||
|
||
} // namespace flow | ||
|
||
#endif // FLUTTER_FLOW_MATRIX_DECOMPOSITION_H_ |
Oops, something went wrong.