Revert "drm_hwcomposer: remove GLCompositor and the GLWorker thread"

This reverts commit abebc7a78fe8a4df6495c8e5064719dc92b04004.

For now until we figure out a more stable solution for SF/hwc

Change-Id: I7a505fc67873f943704e8b48db4167b9beca7691
diff --git a/gl_compositor.cpp b/gl_compositor.cpp
new file mode 100644
index 0000000..0605c04
--- /dev/null
+++ b/gl_compositor.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#define LOG_TAG "GLCompositor"
+
+#include <vector>
+
+#include <cutils/log.h>
+
+#include <ui/GraphicBuffer.h>
+#include <utils/Trace.h>
+
+#include <sync/sync.h>
+#include <sw_sync.h>
+
+#include "drm_hwcomposer.h"
+
+#include "gl_compositor.h"
+#include "glworker.h"
+
+namespace android {
+
+static const char *get_gl_error(void);
+static const char *get_egl_error(void);
+static bool has_extension(const char *extension, const char *extensions);
+
+template <typename T>
+int AllocResource(std::vector<T> &array) {
+  for (typename std::vector<T>::iterator it = array.begin(); it != array.end();
+       ++it) {
+    if (!it->is_some()) {
+      return std::distance(array.begin(), it);
+    }
+  }
+
+  array.push_back(T());
+  return array.size() - 1;
+}
+
+template <typename T>
+void FreeResource(std::vector<T> &array, int index) {
+  if (index == (int)array.size() - 1) {
+    array.pop_back();
+  } else if (index >= 0 && (unsigned)index < array.size()) {
+    array[index].Reset();
+  }
+}
+
+struct GLTarget {
+  sp<GraphicBuffer> fb;
+  bool forgotten;
+  unsigned composition_count;
+
+  GLTarget() : forgotten(true), composition_count(0) {
+  }
+
+  void Reset() {
+    fb.clear();
+    forgotten = true;
+    composition_count = 0;
+  }
+
+  bool is_some() const {
+    return fb != NULL;
+  }
+};
+
+struct GLCompositor::priv_data {
+  int current_target;
+  std::vector<GLTarget> targets;
+  std::vector<GLComposition *> compositions;
+
+  GLWorker worker;
+
+  priv_data() : current_target(-1) {
+  }
+};
+
+class GLComposition : public Composition {
+ public:
+  struct LayerData {
+    hwc_layer_1 layer;
+    hwc_drm_bo bo;
+  };
+
+  GLComposition(GLCompositor *owner, Importer *imp)
+      : compositor(owner), importer(imp), target_handle(-1), timeline_fd(-1) {
+    int ret = sw_sync_timeline_create();
+    if (ret < 0) {
+      ALOGE("Failed to create sw sync timeline %d", ret);
+    }
+    timeline_fd = ret;
+  }
+
+  virtual ~GLComposition() {
+    if (timeline_fd >= 0)
+      close(timeline_fd);
+
+    if (compositor == NULL) {
+      return;
+    }
+
+    // Removes this composition from the owning compositor automatically.
+    std::vector<GLComposition *> &compositions =
+        compositor->priv_->compositions;
+    std::vector<GLComposition *>::iterator it =
+        std::find(compositions.begin(), compositions.end(), this);
+    if (it != compositions.end()) {
+      compositions.erase(it);
+    }
+
+    GLTarget *target = &compositor->priv_->targets[target_handle];
+    target->composition_count--;
+    compositor->CheckAndDestroyTarget(target_handle);
+  }
+
+  virtual int AddLayer(int display, hwc_layer_1 *layer, hwc_drm_bo *bo) {
+    (void)display;
+    if (layer->compositionType != HWC_OVERLAY) {
+      ALOGE("Must add layers with compositionType == HWC_OVERLAY");
+      return 1;
+    }
+
+    if (layer->handle == 0) {
+      ALOGE("Must add layers with valid buffer handle");
+      return 1;
+    }
+
+    layer->releaseFenceFd = sw_sync_fence_create(
+        timeline_fd, "GLComposition release fence", layers.size() + 1);
+
+    layers.push_back(*layer);
+
+    return importer->ReleaseBuffer(bo);
+  }
+
+  virtual unsigned GetRemainingLayers(int display, unsigned num_needed) const {
+    (void)display;
+    return num_needed;
+  }
+
+  GLCompositor *compositor;
+  Importer *importer;
+  int target_handle;
+  int timeline_fd;
+  std::vector<hwc_layer_1> layers;
+};
+
+GLCompositor::GLCompositor() {
+  priv_ = new priv_data;
+}
+
+GLCompositor::~GLCompositor() {
+  for (std::vector<GLComposition *>::iterator it = priv_->compositions.end();
+       it != priv_->compositions.begin(); it = priv_->compositions.end()) {
+    --it;
+
+    // Prevents compositor from trying to erase itself
+    (*it)->compositor = NULL;
+    delete *it;
+    priv_->compositions.erase(it);
+  }
+
+  delete priv_;
+}
+
+int GLCompositor::Init() {
+  return priv_->worker.Init();
+}
+
+Targeting *GLCompositor::targeting() {
+  return (Targeting *)this;
+}
+
+int GLCompositor::CreateTarget(sp<GraphicBuffer> &buffer) {
+  int ret;
+
+  int target_handle = AllocResource(priv_->targets);
+  GLTarget *target = &priv_->targets[target_handle];
+
+  target->fb = buffer;
+  target->forgotten = false;
+
+  return target_handle;
+}
+
+void GLCompositor::SetTarget(int target_handle) {
+  if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) {
+    GLTarget *target = &priv_->targets[target_handle];
+    if (target->is_some()) {
+      priv_->current_target = target_handle;
+      return;
+    }
+  }
+
+  priv_->current_target = -1;
+}
+
+void GLCompositor::ForgetTarget(int target_handle) {
+  if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) {
+    if (target_handle == priv_->current_target) {
+      priv_->current_target = -1;
+    }
+
+    GLTarget *target = &priv_->targets[target_handle];
+    if (target->is_some()) {
+      target->forgotten = true;
+      CheckAndDestroyTarget(target_handle);
+      return;
+    }
+  }
+
+  ALOGE("Failed to forget target because of invalid handle");
+}
+
+void GLCompositor::CheckAndDestroyTarget(int target_handle) {
+  GLTarget *target = &priv_->targets[target_handle];
+  if (target->composition_count == 0 && target->forgotten) {
+    FreeResource(priv_->targets, target_handle);
+  }
+}
+
+Composition *GLCompositor::CreateComposition(Importer *importer) {
+  if (priv_->current_target >= 0 &&
+      (unsigned)priv_->current_target < priv_->targets.size()) {
+    GLTarget *target = &priv_->targets[priv_->current_target];
+    if (target->is_some()) {
+      GLComposition *composition = new GLComposition(this, importer);
+      composition->target_handle = priv_->current_target;
+      target->composition_count++;
+      priv_->compositions.push_back(composition);
+      return composition;
+    }
+  }
+
+  ALOGE("Failed to create composition because of invalid target handle %d",
+        priv_->current_target);
+
+  return NULL;
+}
+
+int GLCompositor::QueueComposition(Composition *composition) {
+  if (composition) {
+    GLComposition *gl_composition = (GLComposition *)composition;
+    int ret = DoComposition(gl_composition);
+    gl_composition->timeline_fd = -1;
+    delete composition;
+    return ret;
+  }
+
+  ALOGE("Failed to queue composition because of invalid composition handle");
+
+  return -EINVAL;
+}
+
+int GLCompositor::Composite() {
+  return 0;
+}
+
+int GLCompositor::DoComposition(GLComposition *composition) {
+  ATRACE_CALL();
+  int ret = 0;
+
+  GLTarget *target = &priv_->targets[composition->target_handle];
+  GLWorker::Work work;
+  work.layers = composition->layers.data();
+  work.num_layers = composition->layers.size();
+  work.timeline_fd = composition->timeline_fd;
+  work.framebuffer = target->fb;
+
+  ret = priv_->worker.DoWork(&work);
+
+  if (work.timeline_fd >= 0) {
+    sw_sync_timeline_inc(work.timeline_fd, work.num_layers + 1);
+    close(work.timeline_fd);
+  }
+
+  return ret;
+}
+
+}  // namespace android