Cap scales used for tessellation with minimum and maximum
bug:15615144
Change-Id: I3e833864af3a7b34e444bd13db34b6c90496a8b6
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 910f862..a410aa9 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -386,9 +386,6 @@
@Override
public void scale(float sx, float sy) {
- // TODO: remove
- if (sx > 1000000 || sy > 1000000) throw new IllegalArgumentException("invalid scales passed " + sx + ", " + sy);
-
nScale(mRenderer, sx, sy);
}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index eee4973..099f153 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -598,9 +598,6 @@
* @see #getScaleX()
*/
public boolean setScaleX(float scaleX) {
- if (scaleX > 1000000) {
- throw new IllegalArgumentException("Invalid scale: " + scaleX);
- }
return nSetScaleX(mNativeRenderNode, scaleX);
}
@@ -622,9 +619,6 @@
* @see #getScaleY()
*/
public boolean setScaleY(float scaleY) {
- if (scaleY > 1000000) {
- throw new IllegalArgumentException("Invalid scale: " + scaleY);
- }
return nSetScaleY(mNativeRenderNode, scaleY);
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e00d2e3..396c7f3 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -58,11 +58,6 @@
// Defines
///////////////////////////////////////////////////////////////////////////////
-#define RAD_TO_DEG (180.0f / 3.14159265f)
-#define MIN_ANGLE 0.001f
-
-#define ALPHA_THRESHOLD 0
-
static GLenum getFilter(const SkPaint* paint) {
if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
return GL_LINEAR;
@@ -692,7 +687,7 @@
(fboLayer && clip.isEmpty())) {
mSnapshot->empty = fboLayer;
} else {
- mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
+ mSnapshot->invisible = mSnapshot->invisible || (alpha <= 0 && fboLayer);
}
}
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 209341c..e30ac19 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -49,6 +49,7 @@
#include "Matrix.h"
#include "Vector.h"
#include "Vertex.h"
+#include "utils/MathUtils.h"
namespace android {
namespace uirenderer {
@@ -56,12 +57,11 @@
#define OUTLINE_REFINE_THRESHOLD_SQUARED (0.5f * 0.5f)
#define ROUND_CAP_THRESH 0.25f
#define PI 3.1415926535897932f
+#define MAX_DEPTH 15
-// temporary error thresholds
-#define ERROR_DEPTH 20
-#define ERROR_SCALE 1e10
-#define ERROR_SQR_INV_THRESH 1e-20
-
+/**
+ * Extracts the x and y scale from the transform as positive values, and clamps them
+ */
void PathTessellator::extractTessellationScales(const Matrix4& transform,
float* scaleX, float* scaleY) {
if (CC_LIKELY(transform.isPureTranslate())) {
@@ -72,11 +72,8 @@
float m01 = transform.data[Matrix4::kSkewY];
float m10 = transform.data[Matrix4::kSkewX];
float m11 = transform.data[Matrix4::kScaleY];
- *scaleX = sqrt(m00 * m00 + m01 * m01);
- *scaleY = sqrt(m10 * m10 + m11 * m11);
-
- LOG_ALWAYS_FATAL_IF(*scaleX > ERROR_SCALE || *scaleY > ERROR_SCALE,
- "scales %e x %e too large for tessellation", *scaleX, *scaleY);
+ *scaleX = MathUtils::clampTessellationScale(sqrt(m00 * m00 + m01 * m01));
+ *scaleY = MathUtils::clampTessellationScale(sqrt(m10 * m10 + m11 * m11));
}
}
@@ -109,8 +106,8 @@
} else {
float scaleX, scaleY;
PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY);
- inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f;
- inverseScaleY = (scaleY != 0) ? (1.0f / scaleY) : 1.0f;
+ inverseScaleX = 1.0f / scaleX;
+ inverseScaleY = 1.0f / scaleY;
}
if (isAA && halfStrokeWidth != 0 && inverseScaleX == inverseScaleY &&
@@ -914,9 +911,6 @@
Vector<Vertex>& outputVertices) {
ATRACE_CALL();
- LOG_ALWAYS_FATAL_IF(sqrInvScaleX < ERROR_SQR_INV_THRESH || sqrInvScaleY < ERROR_SQR_INV_THRESH,
- "Invalid scale factors used for approx %e, %e", sqrInvScaleX, sqrInvScaleY);
-
// TODO: to support joins other than sharp miter, join vertices should be labelled in the
// perimeter, or resolved into more vertices. Reconsider forceClose-ing in that case.
SkPath::Iter iter(path, forceClose);
@@ -975,9 +969,6 @@
float p2x, float p2y, float c2x, float c2y,
float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
Vector<Vertex>& outputVertices, int depth) {
- LOG_ALWAYS_FATAL_IF(depth >= ERROR_DEPTH, "ERROR DEPTH exceeded: cubic approx, invscale %e x %e, vertcount %d",
- sqrInvScaleX, sqrInvScaleY, outputVertices.size());
-
float dx = p2x - p1x;
float dy = p2y - p1y;
float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx);
@@ -985,7 +976,8 @@
float d = d1 + d2;
// multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors
- if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
+ if (depth >= MAX_DEPTH
+ || d * d <= thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
// below thresh, draw line by adding endpoint
pushToVector(outputVertices, p2x, p2y);
} else {
@@ -1023,14 +1015,13 @@
float cx, float cy,
float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
Vector<Vertex>& outputVertices, int depth) {
- LOG_ALWAYS_FATAL_IF(depth >= ERROR_DEPTH, "ERROR_DEPTH exceeded: quadratic approx, invscale %e x %e, vertcount %d",
- sqrInvScaleX, sqrInvScaleY, outputVertices.size());
-
float dx = bx - ax;
float dy = by - ay;
float d = (cx - bx) * dy - (cy - by) * dx;
- if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
+ // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors
+ if (depth >= MAX_DEPTH
+ || d * d <= thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
// below thresh, draw line by adding endpoint
pushToVector(outputVertices, bx, by);
} else {
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 41f48cd..0c8d07f 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -313,7 +313,6 @@
}
bool setScaleX(float scaleX) {
- LOG_ALWAYS_FATAL_IF(scaleX > 1000000, "invalid scaleX %e", scaleX);
return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
}
@@ -322,7 +321,6 @@
}
bool setScaleY(float scaleY) {
- LOG_ALWAYS_FATAL_IF(scaleY > 1000000, "invalid scaleY %e", scaleY);
return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
}
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 66bc127..6fb0411 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -35,6 +35,9 @@
return value >= NON_ZERO_EPSILON;
}
+ /**
+ * Clamps alpha value, and snaps when very near 0 or 1
+ */
inline static float clampAlpha(float alpha) {
if (alpha <= ALPHA_EPSILON) {
return 0;
@@ -45,6 +48,20 @@
}
}
+ /*
+ * Clamps positive tessellation scale values
+ */
+ inline static float clampTessellationScale(float scale) {
+ const float MIN_SCALE = 0.0001;
+ const float MAX_SCALE = 1e10;
+ if (scale < MIN_SCALE) {
+ return MIN_SCALE;
+ } else if (scale > MAX_SCALE) {
+ return MAX_SCALE;
+ }
+ return scale;
+ }
+
inline static bool areEqual(float valueA, float valueB) {
return isZero(valueA - valueB);
}