drm_hwcomposer: implement the safe handling of layers

This is a sweeping change to discard our usage of struct hwc_layer_t outside
hwcomposer.cpp. That was a dangerous struct that was a source of many of our
errors. Replacing it with safer RAII-style classes reduces the amount and
complexity of our code.

Change-Id: I580cafdf89bd1e7e6583f3073858b8e78e6018ba
diff --git a/drm_hwcomposer.h b/drm_hwcomposer.h
index cebdbee..fdf389b 100644
--- a/drm_hwcomposer.h
+++ b/drm_hwcomposer.h
@@ -22,6 +22,7 @@
 
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
+#include "seperate_rects.h"
 
 struct hwc_import_context;
 
@@ -71,4 +72,202 @@
 bool hwc_import_bo_release(int fd, struct hwc_import_context *ctx,
                            struct hwc_drm_bo *bo);
 
+namespace android {
+
+class Importer;
+
+class UniqueFd {
+ public:
+  UniqueFd() = default;
+  UniqueFd(int fd) : fd_(fd) {
+  }
+  UniqueFd(UniqueFd &&rhs) {
+    fd_ = rhs.fd_;
+    rhs.fd_ = -1;
+  }
+
+  UniqueFd &operator=(UniqueFd &&rhs) {
+    Set(rhs.Release());
+    return *this;
+  }
+
+  ~UniqueFd() {
+    if (fd_ >= 0)
+      close(fd_);
+  }
+
+  int Release() {
+    int old_fd = fd_;
+    fd_ = -1;
+    return old_fd;
+  }
+
+  int Set(int fd) {
+    if (fd_ >= 0)
+      close(fd_);
+    fd_ = fd;
+    return fd_;
+  }
+
+  void Close() {
+    if (fd_ >= 0)
+      close(fd_);
+    fd_ = -1;
+  }
+
+  int get() {
+    return fd_;
+  }
+
+ private:
+  int fd_ = -1;
+};
+
+struct OutputFd {
+  OutputFd() = default;
+  OutputFd(int *fd) : fd_(fd) {
+  }
+  OutputFd(OutputFd &&rhs) {
+    fd_ = rhs.fd_;
+    rhs.fd_ = NULL;
+  }
+
+  OutputFd &operator=(OutputFd &&rhs);
+
+  int Set(int fd) {
+    if (*fd_ >= 0)
+      close(*fd_);
+    *fd_ = fd;
+    return fd;
+  }
+
+  int get() {
+    return *fd_;
+  }
+
+ private:
+  int *fd_ = NULL;
+};
+
+class DrmHwcBuffer {
+ public:
+  DrmHwcBuffer() = default;
+  DrmHwcBuffer(const hwc_drm_bo &bo, Importer *importer)
+      : bo_(bo), importer_(importer) {
+  }
+  DrmHwcBuffer(DrmHwcBuffer &&rhs) : bo_(rhs.bo_), importer_(rhs.importer_) {
+    rhs.importer_ = NULL;
+  }
+
+  ~DrmHwcBuffer() {
+    Clear();
+  }
+
+  DrmHwcBuffer &operator=(DrmHwcBuffer &&rhs) {
+    Clear();
+    importer_ = rhs.importer_;
+    rhs.importer_ = NULL;
+    bo_ = rhs.bo_;
+    return *this;
+  }
+
+  operator bool() {
+    return importer_ != NULL;
+  }
+
+  hwc_drm_bo *operator->();
+
+  void Clear();
+
+  int ImportBuffer(buffer_handle_t handle, Importer *importer);
+
+ private:
+  hwc_drm_bo bo_;
+  Importer *importer_ = NULL;
+};
+
+class DrmHwcNativeHandle {
+ public:
+  DrmHwcNativeHandle() = default;
+
+  DrmHwcNativeHandle(const gralloc_module_t *gralloc, native_handle_t *handle)
+      : gralloc_(gralloc), handle_(handle) {
+  }
+
+  DrmHwcNativeHandle(DrmHwcNativeHandle &&rhs) {
+    gralloc_ = rhs.gralloc_;
+    rhs.gralloc_ = NULL;
+    handle_ = rhs.handle_;
+    rhs.handle_ = NULL;
+  }
+
+  ~DrmHwcNativeHandle();
+
+  DrmHwcNativeHandle &operator=(DrmHwcNativeHandle &&rhs) {
+    Clear();
+    gralloc_ = rhs.gralloc_;
+    rhs.gralloc_ = NULL;
+    handle_ = rhs.handle_;
+    rhs.handle_ = NULL;
+    return *this;
+  }
+
+  int CopyBufferHandle(buffer_handle_t handle, const gralloc_module_t *gralloc);
+
+  void Clear();
+
+  buffer_handle_t get() const {
+    return handle_;
+  }
+
+ private:
+  const gralloc_module_t *gralloc_ = NULL;
+  native_handle_t *handle_ = NULL;
+};
+
+template <typename T>
+using DrmHwcRect = seperate_rects::Rect<T>;
+
+enum class DrmHwcTransform : uint32_t {
+  kIdentity = 0,
+  kFlipH = HWC_TRANSFORM_FLIP_H,
+  kFlipV = HWC_TRANSFORM_FLIP_V,
+  kRotate90 = HWC_TRANSFORM_ROT_90,
+  kRotate180 = HWC_TRANSFORM_ROT_180,
+  kRotate270 = HWC_TRANSFORM_ROT_270,
+};
+
+enum class DrmHwcBlending : int32_t {
+  kNone = HWC_BLENDING_NONE,
+  kPreMult = HWC_BLENDING_PREMULT,
+  kCoverage = HWC_BLENDING_COVERAGE,
+};
+
+struct DrmHwcLayer {
+  buffer_handle_t sf_handle = NULL;
+  DrmHwcBuffer buffer;
+  DrmHwcNativeHandle handle;
+  DrmHwcTransform transform = DrmHwcTransform::kIdentity;
+  DrmHwcBlending blending = DrmHwcBlending::kNone;
+  uint8_t alpha = 0xff;
+  DrmHwcRect<float> source_crop;
+  DrmHwcRect<int> display_frame;
+  std::vector<DrmHwcRect<int>> source_damage;
+
+  UniqueFd acquire_fence;
+  OutputFd release_fence;
+
+  DrmHwcLayer() = default;
+  DrmHwcLayer(DrmHwcLayer &&rhs) = default;
+
+  int InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
+                       const gralloc_module_t *gralloc);
+};
+
+struct DrmHwcDisplayContents {
+  OutputFd retire_fence;
+  std::vector<DrmHwcLayer> layers;
+};
+}
+
 #endif