Shared memory primitives for dealing with graphics

Change-Id: I49fcbb4257664c3cd8db346cd6e6d1702fc3912d
diff --git a/common/vsoc/lib/BUILD b/common/vsoc/lib/BUILD
index f882f37..d308e2a 100644
--- a/common/vsoc/lib/BUILD
+++ b/common/vsoc/lib/BUILD
@@ -1,3 +1,15 @@
+cc_test(
+    name = "vsoc_graphics_test",
+    srcs = [
+        "graphics_test.cpp",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//common/vsoc/shm",
+        "@gtest_repo//:gtest_main",
+    ],
+)
+
 cc_library(
     name = "vsoc_common",
     srcs = [
@@ -5,12 +17,14 @@
         "region_common.cpp",
     ],
     hdrs = [
+        "graphics_common.h",
         "region.h",
     ],
     copts = ["-Wno-unused-private-field"],
     visibility = ["//visibility:public"],
     deps = [
         "//common/libs/fs",
+        "//common/vsoc/shm",
         "@kernel//:uapi",
     ],
 )
diff --git a/common/vsoc/lib/graphics_common.h b/common/vsoc/lib/graphics_common.h
new file mode 100644
index 0000000..d2db6c4
--- /dev/null
+++ b/common/vsoc/lib/graphics_common.h
@@ -0,0 +1,28 @@
+#pragma once
+
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "common/vsoc/shm/graphics.h"
+
+namespace vsoc {
+
+// Returns BytesPerPixel given a PixelFormat. Code should rely on this rather
+// than accessing the mask directly.
+static inline std::size_t BytesPerPixel(PixelFormat in) {
+    return 1 + (in >> PixelFormatBase::SubformatSize) &
+        (PixelFormatBase::MaxBytesPerPixel - 1);
+}
+}  // vsoc
diff --git a/common/vsoc/lib/graphics_test.cpp b/common/vsoc/lib/graphics_test.cpp
new file mode 100644
index 0000000..b43e56e
--- /dev/null
+++ b/common/vsoc/lib/graphics_test.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "common/vsoc/shm/graphics.h"
+
+#include <gtest/gtest.h>
+
+TEST(GraphicsTest, Basic) {
+  // This is a shared memory layout and is mostly tested via static asserts.
+  // If this can compile then the test has passed.
+}
diff --git a/common/vsoc/shm/BUILD b/common/vsoc/shm/BUILD
index 1ae47df..4b0ef9b 100644
--- a/common/vsoc/shm/BUILD
+++ b/common/vsoc/shm/BUILD
@@ -3,6 +3,7 @@
     hdrs = [
         "base.h",
         "e2e_test_region.h",
+        "graphics.h",
         "version.h",
     ],
     visibility = ["//visibility:public"],
diff --git a/common/vsoc/shm/graphics.h b/common/vsoc/shm/graphics.h
new file mode 100644
index 0000000..2339c2e
--- /dev/null
+++ b/common/vsoc/shm/graphics.h
@@ -0,0 +1,164 @@
+#pragma once
+
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Memory layout for primitive graphics types.
+
+// The vsoc::layout namespace indicates that these are shared memory structure
+// definitions. The #include's given above are strictly limited, as are the
+// types that can be referenced below.
+
+#include <cstdint>
+
+#include "common/vsoc/shm/base.h"
+#include "common/vsoc/shm/version.h"
+
+namespace vsoc {
+
+// The enumerations for VSoC pixel formats are laid out so that hardware to
+// parse bytes per pixel without relying an a exhaustive list of pixel formats.
+// These constants define the fields involved.
+namespace PixelFormatConst {
+  static const uint32_t BytesPerPixelSize = 3;
+  static const uint32_t SubformatSize = 3;
+  static const uint32_t MaxBytesPerPixel = (1 << BytesPerPixelSize);
+  static const uint32_t MaxSubformat = (1 << SubformatSize) - 1;
+};
+
+
+// Builds (statically) a new pixel format enumeration value given constant
+// bytes per pixel.
+template <uint32_t BYTES, uint32_t SUB_FORMAT>
+struct PixelFormatBuilder {
+  static_assert(BYTES > 0, "Too few bytes");
+  static_assert(BYTES <= PixelFormatConst::MaxBytesPerPixel, "Too many bytes");
+  static_assert(SUB_FORMAT <= PixelFormatConst::MaxSubformat,
+                "Too many subformats");
+  static const uint32_t value = ((BYTES - 1) << PixelFormatConst::SubformatSize) | SUB_FORMAT;
+};
+
+// Contains all of the pixel formats currently supported by this VSoC. The
+// enumeration serves multiple purposes:
+//
+//   * The compile will warn (or error) if we switch on PixelFormat and don't
+//     handly all of the cases.
+//
+//   * Code can use PixelFormat to describe paramaters, making APIs a bit more
+//     self-documenting.
+//
+//   * Observant reviewers can verify that the same pixel value is not assigned
+//     to multiple formats. Keep the enums in numerical order below to
+//     make this easier.
+enum PixelFormat {
+  VSOC_PIXEL_FORMAT_UNINITIALIZED = PixelFormatBuilder<1,0>::value,
+  VSOC_PIXEL_FORMAT_BLOB =          PixelFormatBuilder<1,1>::value,
+
+  VSOC_PIXEL_FORMAT_RGB_565 =       PixelFormatBuilder<2,0>::value,
+  VSOC_PIXEL_FORMAT_YV12 =          PixelFormatBuilder<2,1>::value,
+  VSOC_PIXEL_FORMAT_YCbCr_420_888 = PixelFormatBuilder<2,2>::value,
+
+  VSOC_PIXEL_FORMAT_RGB_888 =       PixelFormatBuilder<3,0>::value,
+
+  VSOC_PIXEL_FORMAT_RGBA_8888 =     PixelFormatBuilder<4,0>::value,
+  VSOC_PIXEL_FORMAT_RGBX_8888 =     PixelFormatBuilder<4,1>::value,
+  VSOC_PIXEL_FORMAT_BGRA_8888 =     PixelFormatBuilder<4,2>::value,
+
+  // VSOC_PIXEL_FORMAT_IMPLEMENTATION_DEFINED intentionally left out. The HALs
+  // should choose one of the defined contrete types.
+  //
+  // The following formats are defined in various platform versions, but don't
+  // seem to be used. If we encounter them it's ok to add them to the table.
+  // This does not necessitate a version change.
+  //
+  // The following have been in the framework for a long time:
+  //
+  //   VSOC_PIXEL_FORMAT_YCrCb_420_SP
+  //   VSOC_PIXEL_FORMAT_YCbCr_422_SP
+  //
+  // The following were added in JB_MR2:
+  //
+  //   VSOC_PIXEL_FORMAT_YCbCr_420_888
+  //   VSOC_PIXEL_FORMAT_Y8
+  //   VSOC_PIXEL_FORMAT_Y16
+  //
+  // The following were added in L:
+  //
+  //    VSOC_PIXEL_FORMAT_RAW_OPAQUE
+  //    VSOC_PIXEL_FORMAT_RAW16 (also known as RAW_SENSOR. Define only RAW16)
+  //    VSOC_PIXEL_FORMAT_RAW10
+  //
+  // The following were added in L MR1:
+  //
+  //   VSOC_PIXEL_FORMAT_YCbCr_444_888
+  //   VSOC_PIXEL_FORMAT_YCbCr_422_888
+  //   VSOC_PIXEL_FORMAT_RAW12
+  //   VSOC_PIXEL_FORMAT_FLEX_RGBA_8888
+  //   VSOC_PIXEL_FORMAT_FLEX_RGB_888
+  //
+  // These pixel formats were removed in later framework versions. Implement
+  // only if absolutely necessary.
+  //
+  // Support was dropped in K for:
+  //
+  //   VSOC_PIXEL_FORMAT_RGBA_5551
+  //   VSOC_PIXEL_FORMAT_RGBA_4444
+  //
+  // Supported only in K, L, and LMR1:
+  //
+  //   VSOC_PIXEL_FORMAT_sRGB_X_8888
+  //   VSOC_PIXEL_FORMAT_sRGB_A_8888
+};
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_UNINITIALIZED, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_BLOB, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_RGB_565, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_YV12, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_YCbCr_420_888, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_RGB_888, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_RGBA_8888, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_RGBX_8888, multi_region);
+ASSERT_SHM_CONSTANT_VALUE(VSOC_PIXEL_FORMAT_BGRA_8888, multi_region);
+
+namespace layout {
+
+// VSoC memory layout for a register that accepts a single pixel format.
+// The value is volatile to ensure that the compiler does not eliminate stores.
+struct PixelFormatRegister : public Base {
+  volatile PixelFormat value_;
+};
+ASSERT_SHM_COMPATIBLE(PixelFormatRegister, multi_region);
+
+// Register layout for a mask giving different PixelFormats. Reserve enough
+// space to allow for future expansion. For example, we may well end with
+// a 12 bit per channel format in the future.
+struct PixelFormatMaskRegister {
+  volatile uint64_t value_;
+
+  bool HasValue(PixelFormat in) {
+    return !!(value_ & (uint64_t(1) << in));
+  }
+};
+ASSERT_SHM_COMPATIBLE(PixelFormatMaskRegister, multi_region);
+
+// Ensure that the mask is large enough to hold the highest encodable
+// pixel format.
+static_assert(PixelFormatBuilder<
+              PixelFormatConst::MaxBytesPerPixel,
+              PixelFormatConst::MaxSubformat>::value <
+              8 * sizeof(PixelFormatMaskRegister),
+              "Largest pixel format does not fit in mask");
+}  // layout
+}  // vsoc
diff --git a/common/vsoc/shm/version.h b/common/vsoc/shm/version.h
index d7e5561..f9c31db 100644
--- a/common/vsoc/shm/version.h
+++ b/common/vsoc/shm/version.h
@@ -48,6 +48,23 @@
 }
 
 static const std::size_t Base_size = 1;
+static const std::size_t PixelFormatRegister_size = 4;
+static const std::size_t PixelFormatMaskRegister_size = 8;
+
+namespace constant_values {
+  static const uint32_t VSOC_PIXEL_FORMAT_UNINITIALIZED = 0;
+  static const uint32_t VSOC_PIXEL_FORMAT_BLOB = 1;
+
+  static const uint32_t VSOC_PIXEL_FORMAT_RGB_565 = 8;
+  static const uint32_t VSOC_PIXEL_FORMAT_YV12 = 9;
+  static const uint32_t VSOC_PIXEL_FORMAT_YCbCr_420_888 = 10;
+
+  static const uint32_t VSOC_PIXEL_FORMAT_RGB_888 = 16;
+
+  static const uint32_t VSOC_PIXEL_FORMAT_RGBA_8888 = 24;
+  static const uint32_t VSOC_PIXEL_FORMAT_RGBX_8888 = 25;
+  static const uint32_t VSOC_PIXEL_FORMAT_BGRA_8888 = 26;
+}  // constant_values
 }  // multi_region
 
 // Versioning information for e2e_test_region.h