Add DaydreamVR native libraries and services

Upstreaming the main VR system components from master-dreamos-dev
into goog/master.

Bug: None
Test: `m -j32` succeeds. Sailfish boots and basic_vr sample app works
Change-Id: I853015872afc443aecee10411ef2d6b79184d051
diff --git a/libs/vr/libeds/eds_mesh.cpp b/libs/vr/libeds/eds_mesh.cpp
new file mode 100644
index 0000000..2c7dc2f
--- /dev/null
+++ b/libs/vr/libeds/eds_mesh.cpp
@@ -0,0 +1,136 @@
+#include "include/private/dvr/eds_mesh.h"
+
+#include <math.h>
+
+#include <base/logging.h>
+#include <private/dvr/types.h>
+
+namespace {
+
+using android::dvr::EdsVertex;
+using android::dvr::EyeType;
+using android::dvr::DistortionFunction;
+using android::dvr::vec2;
+
+// Computes the vertices for a distortion mesh with resolution |resolution| and
+// distortion provided by |hmd| and stores them in |vertices|.
+static void ComputeDistortionMeshVertices(
+    EdsVertex* vertices, int resolution,
+    const DistortionFunction& distortion_function, EyeType eye) {
+  for (int row = 0; row < resolution; row++) {
+    for (int col = 0; col < resolution; col++) {
+      const float x_norm =
+          static_cast<float>(col) / (static_cast<float>(resolution - 1U));
+      const float y_norm =
+          static_cast<float>(row) / (static_cast<float>(resolution - 1U));
+
+      const vec2 xy_norm(x_norm, y_norm);
+      const size_t index = col * resolution + row;
+
+      // Evaluate distortion function to get the new coordinates for each color
+      // channel. The distortion function returns the new coordinates relative
+      // to a full viewport with 0 <= x <= 1 for each eye.
+      vec2 coords[3];
+      distortion_function(eye, xy_norm, &vertices[index].position, coords);
+
+      // Store distortion mapping in texture coordinates.
+      vertices[index].red_viewport_coords = coords[0];
+      vertices[index].green_viewport_coords = coords[1];
+      vertices[index].blue_viewport_coords = coords[2];
+    }
+  }
+}
+
+// Computes the triangle strip indices for a distortion mesh with resolution
+// |resolution| and stores them in |indices|.
+static void ComputeDistortionMeshIndices(uint16_t* indices, int resolution) {
+  // The following strip method has been used in the Cardboard SDK
+  // (java/com/google/vrtoolkit/cardboard/DistortionRenderer.java) and has
+  // originally been described at:
+  //
+  // http://dan.lecocq.us/wordpress/2009/12/25/triangle-strip-for-grids-a-construction/
+  //
+  // For a grid with 4 rows and 4 columns of vertices, the strip would
+  // look like:
+  //                             ↻
+  //         0    -    4    -    8    -   12
+  //         ↓    ↗    ↓    ↗    ↓    ↗    ↓
+  //         1    -    5    -    9    -   13
+  //         ↓    ↖    ↓    ↖    ↓    ↖    ↓
+  //         2    -    6    -   10    -   14
+  //         ↓    ↗    ↓    ↗    ↓    ↗    ↓
+  //         3    -    7    -   11    -   15
+  //                   ↺
+  //
+  // Note the little circular arrows next to 7 and 8 that indicate
+  // repeating that vertex once so as to produce degenerate triangles.
+  //
+  // To facilitate scanline racing, the vertex order is left to right.
+
+  int16_t index_offset = 0;
+  int16_t vertex_offset = 0;
+  for (int row = 0; row < resolution - 1; ++row) {
+    if (row > 0) {
+      indices[index_offset] = indices[index_offset - 1];
+      ++index_offset;
+    }
+    for (int col = 0; col < resolution; ++col) {
+      if (col > 0) {
+        if (row % 2 == 0) {
+          // Move right on even rows.
+          ++vertex_offset;
+        } else {
+          --vertex_offset;
+        }
+      }
+      // A cast to uint16_t is safe here as |vertex_offset| will not drop below
+      // zero in this loop. As col is initially equal to zero |vertex_offset| is
+      // always incremented before being decremented, is initialized to zero and
+      // is only incremented outside of the loop.
+      indices[index_offset++] = static_cast<uint16_t>(vertex_offset);
+      indices[index_offset++] = static_cast<uint16_t>(
+          vertex_offset + static_cast<int16_t>(resolution));
+    }
+    vertex_offset =
+        static_cast<int16_t>(static_cast<int>(resolution) + vertex_offset);
+  }
+}
+
+}  // anonymous namespace
+
+namespace android {
+namespace dvr {
+
+// Builds a distortion mesh of resolution |resolution| using the distortion
+// provided by |hmd| for |eye|.
+EdsMesh BuildDistortionMesh(EyeType eye, int resolution,
+                            const DistortionFunction& distortion_function) {
+  CHECK_GT(resolution, 2);
+
+  // Number of indices produced by the strip method
+  // (see comment in ComputeDistortionMeshIndices):
+  //
+  //     1 vertex per triangle
+  //     2 triangles per quad, (rows - 1) * (cols - 1) quads
+  //     2 vertices at the start of each row for the first triangle
+  //     1 extra vertex per row (except first and last) for a
+  //       degenerate triangle
+  //
+  const uint16_t index_count =
+      static_cast<uint16_t>(resolution * (2 * resolution - 1U) - 2U);
+  const uint16_t vertex_count = static_cast<uint16_t>(resolution * resolution);
+
+  EdsMesh mesh;
+  mesh.vertices.resize(vertex_count);
+  mesh.indices.resize(index_count);
+
+  // Populate vertex and index buffer.
+  ComputeDistortionMeshVertices(&mesh.vertices[0], resolution,
+                                distortion_function, eye);
+  ComputeDistortionMeshIndices(&mesh.indices[0], resolution);
+
+  return mesh;
+}
+
+}  // namespace dvr
+}  // namespace android