summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/blackberry/LayerUtilities.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/blackberry/LayerUtilities.h')
-rw-r--r--Source/WebCore/platform/graphics/blackberry/LayerUtilities.h308
1 files changed, 308 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerUtilities.h b/Source/WebCore/platform/graphics/blackberry/LayerUtilities.h
new file mode 100644
index 000000000..19aa1995f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/LayerUtilities.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2013 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LayerUtilities_h
+#define LayerUtilities_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "FloatQuad.h"
+#include "FloatSize.h"
+#include "LayerCompositingThread.h"
+#include "TransformationMatrix.h"
+
+#include <algorithm>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// determinant of column vectors
+inline float determinant(const FloatSize& a, const FloatSize& b)
+{
+ return a.width() * b.height() - a.height() * b.width();
+}
+
+// dot product
+inline float dot(const FloatSize& a, const FloatSize& b)
+{
+ return a.width() * b.width() + a.height() * b.height();
+}
+
+// Represents a line, not a finite line segment
+class LayerClipEdge {
+public:
+ LayerClipEdge(const FloatPoint& first, const FloatPoint& second)
+ : m_first(first)
+ , m_second(second)
+ {
+ }
+
+ inline bool isPointInside(const FloatPoint& p) const
+ {
+ // For numeric robustness, we prefer to consider a point to be inside rather than
+ // clip it again.
+ const float epsilon = 1e-6;
+ return determinant(m_second - m_first, p - m_first) > -epsilon;
+ }
+
+ inline FloatPoint computeIntersection(const FloatPoint& p1, const FloatPoint& p2) const
+ {
+ const FloatPoint& p3 = m_first;
+ const FloatPoint& p4 = m_second;
+ float denominator = determinant(p1 - p2, p3 - p4);
+ FloatSize determinants(determinant(toFloatSize(p1), toFloatSize(p2)), determinant(toFloatSize(p3), toFloatSize(p4)));
+ FloatPoint result(
+ determinant(determinants, FloatSize(p1.x() - p2.x(), p3.x() - p4.x())) / denominator,
+ determinant(determinants, FloatSize(p1.y() - p2.y(), p3.y() - p4.y())) / denominator);
+ return result;
+ }
+
+private:
+ FloatPoint m_first;
+ FloatPoint m_second;
+};
+
+// Specifies a clip plane with normal n and containing point p_0
+// as p * n + d = 0, d = -p_0 * n. The asterisk is dot product.
+class LayerClipPlane {
+public:
+ LayerClipPlane(FloatPoint3D n, float d)
+ : m_n(n)
+ , m_d(d)
+ {
+ }
+
+ inline bool isPointInside(const FloatPoint3D& p) const
+ {
+ return p * m_n + m_d > 0;
+ }
+
+ inline FloatPoint3D computeIntersection(const FloatPoint3D& p1, const FloatPoint3D& p2) const
+ {
+ float u = (-m_d - p1 * m_n) / ((p2 - p1) * m_n);
+ return p1 + u * (p2 - p1);
+ }
+
+protected:
+ FloatPoint3D m_n;
+ float m_d;
+};
+
+// Sutherland - Hodgman, inner loop
+template<typename Point, size_t inlineCapacity, typename ClipPrimitive>
+inline Vector<Point, inlineCapacity> intersect(const Vector<Point, inlineCapacity>& inputList, const ClipPrimitive& clipPrimitive)
+{
+ Vector<Point, inlineCapacity> outputList;
+ Point s;
+ if (!inputList.isEmpty())
+ s = inputList.last();
+ for (typename Vector<Point, inlineCapacity>::const_iterator eIterator = inputList.begin(); eIterator != inputList.end(); ++eIterator) {
+ const Point& e = *eIterator;
+ if (clipPrimitive.isPointInside(e)) {
+ if (!clipPrimitive.isPointInside(s))
+ outputList.append(clipPrimitive.computeIntersection(s, e));
+ outputList.append(e);
+ } else if (clipPrimitive.isPointInside(s))
+ outputList.append(clipPrimitive.computeIntersection(s, e));
+ s = e;
+ }
+ return outputList;
+}
+
+// Sutherland - Hodgman, main driver
+template<size_t inlineCapacity>
+inline Vector<FloatPoint, inlineCapacity> intersectPolygonWithRect(const Vector<FloatPoint, inlineCapacity>& subjectPolygon, const FloatRect& clipRect)
+{
+ FloatQuad clipQuad(clipRect);
+ Vector<LayerClipEdge> edges;
+ edges.append(LayerClipEdge(clipQuad.p1(), clipQuad.p2()));
+ edges.append(LayerClipEdge(clipQuad.p2(), clipQuad.p3()));
+ edges.append(LayerClipEdge(clipQuad.p3(), clipQuad.p4()));
+ edges.append(LayerClipEdge(clipQuad.p4(), clipQuad.p1()));
+
+ Vector<FloatPoint> outputList = subjectPolygon;
+ for (Vector<LayerClipEdge>::const_iterator clipEdgeIterator = edges.begin(); clipEdgeIterator != edges.end(); ++clipEdgeIterator) {
+ const LayerClipEdge& clipEdge = *clipEdgeIterator;
+ Vector<FloatPoint> inputList = outputList;
+ outputList = intersect(inputList, clipEdge);
+ }
+ return outputList;
+}
+
+template<size_t inlineCapacity>
+inline FloatRect boundingBox(const Vector<FloatPoint, inlineCapacity>& points)
+{
+ if (points.isEmpty())
+ return FloatRect();
+ float xmin, xmax, ymin, ymax;
+ xmin = ymin = std::numeric_limits<float>::infinity();
+ xmax = ymax = -std::numeric_limits<float>::infinity();
+ for (size_t i = 0; i < points.size(); ++i) {
+ const FloatPoint& p = points[i];
+ if (p.x() < xmin)
+ xmin = p.x();
+ if (p.x() > xmax)
+ xmax = p.x();
+ if (p.y() < ymin)
+ ymin = p.y();
+ if (p.y() > ymax)
+ ymax = p.y();
+ }
+ return FloatRect(xmin, ymin, xmax - xmin, ymax - ymin);
+}
+
+inline FloatPoint3D computeBarycentricCoordinates(const FloatPoint& p, const FloatPoint& t1, const FloatPoint& t2, const FloatPoint& t3, bool& ok)
+{
+ // Compute vectors
+ FloatSize v0 = t2 - t1;
+ FloatSize v1 = t3 - t1;
+ FloatSize v2 = p - t1;
+
+ // Compute dot products
+ float dot00 = dot(v0, v0);
+ float dot01 = dot(v0, v1);
+ float dot02 = dot(v0, v2);
+ float dot11 = dot(v1, v1);
+ float dot12 = dot(v1, v2);
+
+ // Compute barycentric coordinates
+ float denominator = (dot00 * dot11 - dot01 * dot01);
+ ok = (denominator != 0.0);
+ if (!ok)
+ return FloatPoint3D();
+
+ float v = (dot11 * dot02 - dot01 * dot12) / denominator;
+ float w = (dot00 * dot12 - dot01 * dot02) / denominator;
+
+ return FloatPoint3D(1.0f - v - w, v, w);
+}
+
+inline float manhattanDistanceToViewport(const FloatPoint& p)
+{
+ float d = 0;
+ if (fabsf(p.x()) > 1)
+ d += fabsf(p.x()) - 1;
+ if (fabsf(p.y()) > 1)
+ d += fabsf(p.y()) - 1;
+ return d;
+}
+
+struct UnprojectionVertex {
+ FloatPoint xy;
+ float w;
+ FloatSize uv;
+};
+
+inline bool compareManhattanDistanceToViewport(const UnprojectionVertex& a, const UnprojectionVertex& b)
+{
+ return manhattanDistanceToViewport(a.xy) < manhattanDistanceToViewport(b.xy);
+}
+
+template<size_t inlineCapacity>
+inline Vector<FloatPoint, inlineCapacity> unproject(LayerCompositingThread* layer, const Vector<FloatPoint, inlineCapacity>& points)
+{
+ // Use perspective correct texturing logic to find the locations of these points in normalized layer coordinates
+ Vector<FloatPoint, 4> bounds = layer->transformedBounds();
+ Vector<float, 4> ws = layer->ws();
+ if (ws.isEmpty())
+ ws.fill(0.0f, bounds.size());
+ const Vector<FloatPoint>& texCoords = layer->textureCoordinates();
+ if (bounds.size() < 3)
+ return Vector<FloatPoint, inlineCapacity>();
+
+ Vector<UnprojectionVertex, 4> vertices(bounds.size());
+ for (size_t i = 0; i < bounds.size(); ++i) {
+ vertices[i].xy = bounds[i];
+ vertices[i].w = ws[i];
+ vertices[i].uv = toFloatSize(texCoords[i]);
+ }
+ // Each point needs to be qualified as lying in one of the triangles formed by the "bounds" triangle strip
+ // Try to use only points that are onscreen, for numerical stability
+ std::sort(vertices.begin(), vertices.end(), compareManhattanDistanceToViewport);
+
+ Vector<FloatPoint, inlineCapacity> result;
+
+ size_t i0 = 0;
+
+ const FloatPoint& p0 = vertices[i0].xy;
+ float w0 = vertices[i0].w;
+ FloatSize uv0 = vertices[i0].uv;
+
+ for (size_t j = 0; j < points.size(); ++j) {
+ const FloatPoint& p = points[j];
+ FloatPoint texCoord;
+ for (size_t di = 1; di + 1 < vertices.size(); ++di) {
+ size_t i = (i0 + di) % vertices.size();
+ const FloatPoint& p1 = vertices[i].xy;
+ const FloatPoint& p2 = vertices[i + 1].xy;
+ float w1 = vertices[i].w;
+ float w2 = vertices[i + 1].w;
+ FloatSize uv1 = vertices[i].uv;
+ FloatSize uv2 = vertices[i + 1].uv;
+
+ bool ok;
+ FloatPoint3D b = computeBarycentricCoordinates(p, p0, p1, p2, ok);
+ if (!ok)
+ continue;
+
+ if (w0 && w1 && w2) {
+ // Perspective correct interpolation
+ FloatPoint3D bw(b.x() / w0, b.y() / w1, b.z() / w2);
+ float denominator = bw.x() + bw.y() + bw.z();
+ texCoord = FloatPoint::zero() + (bw.x() * uv0 + bw.y() * uv1 + bw.z() * uv2);
+ texCoord.setX(texCoord.x() / denominator);
+ texCoord.setY(texCoord.y() / denominator);
+ } else {
+ // Linear interpolation
+ texCoord = FloatPoint::zero() + (b.x() * uv0 + b.y() * uv1 + b.z() * uv2);
+ }
+ break;
+ }
+ result.append(texCoord);
+ }
+ return result;
+}
+
+inline FloatPoint3D multVecMatrix(const TransformationMatrix& matrix, const FloatPoint3D& p, float& w)
+{
+ FloatPoint3D result(
+ matrix.m41() + p.x() * matrix.m11() + p.y() * matrix.m21() + p.z() * matrix.m31(),
+ matrix.m42() + p.x() * matrix.m12() + p.y() * matrix.m22() + p.z() * matrix.m32(),
+ matrix.m43() + p.x() * matrix.m13() + p.y() * matrix.m23() + p.z() * matrix.m33());
+ w = matrix.m44() + p.x() * matrix.m14() + p.y() * matrix.m24() + p.z() * matrix.m34();
+ return result;
+}
+
+template<typename Point, size_t inlineCapacity>
+inline Vector<Point, inlineCapacity> toVector(const FloatQuad& quad)
+{
+ Vector<Point, inlineCapacity> result;
+ result.append(quad.p1());
+ result.append(quad.p2());
+ result.append(quad.p3());
+ result.append(quad.p4());
+ return result;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // LayerUtilities_h