Merge "drm_hwcomposer: add transform support to OpenGL compositor" into mnc-dr-dev
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index 364a64e..d8dc886 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -85,9 +85,6 @@
 
 int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo,
                                     DrmCrtc *crtc, DrmPlane *plane) {
-  if (layer->transform != 0)
-    return -EINVAL;
-
   if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
     return -EINVAL;
 
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index 10b4480..0fd6874 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -28,6 +28,7 @@
 #include <time.h>
 #include <vector>
 
+#include <drm/drm_mode.h>
 #include <cutils/log.h>
 #include <sync/sync.h>
 #include <utils/Trace.h>
@@ -95,22 +96,22 @@
 int DrmDisplayCompositor::QueueComposition(
     std::unique_ptr<DrmDisplayComposition> composition) {
   switch (composition->type()) {
-  case DRM_COMPOSITION_TYPE_FRAME:
-    if (!active_)
-      return -ENODEV;
-    break;
-  case DRM_COMPOSITION_TYPE_DPMS:
-    /*
-     * Update the state as soon as we get it so we can start/stop queuing
-     * frames asap.
-     */
-    active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
-    break;
-  case DRM_COMPOSITION_TYPE_EMPTY:
-    return 0;
-  default:
-    ALOGE("Unknown composition type %d/%d", composition->type(), display_);
-    return -ENOENT;
+    case DRM_COMPOSITION_TYPE_FRAME:
+      if (!active_)
+        return -ENODEV;
+      break;
+    case DRM_COMPOSITION_TYPE_DPMS:
+      /*
+       * Update the state as soon as we get it so we can start/stop queuing
+       * frames asap.
+       */
+      active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
+      break;
+    case DRM_COMPOSITION_TYPE_EMPTY:
+      return 0;
+    default:
+      ALOGE("Unknown composition type %d/%d", composition->type(), display_);
+      return -ENOENT;
   }
 
   int ret = pthread_mutex_lock(&lock_);
@@ -173,6 +174,38 @@
       continue;
     }
 
+    uint64_t rotation;
+    switch (layer->transform) {
+      case HWC_TRANSFORM_FLIP_H:
+        rotation = 1 << DRM_REFLECT_X;
+        break;
+      case HWC_TRANSFORM_FLIP_V:
+        rotation = 1 << DRM_REFLECT_Y;
+        break;
+      case HWC_TRANSFORM_ROT_90:
+        rotation = 1 << DRM_ROTATE_90;
+        break;
+      case HWC_TRANSFORM_ROT_180:
+        rotation = 1 << DRM_ROTATE_180;
+        break;
+      case HWC_TRANSFORM_ROT_270:
+        rotation = 1 << DRM_ROTATE_270;
+        break;
+      case 0:
+        rotation = 0;
+        break;
+      default:
+        ALOGE("Invalid transform value 0x%x given", layer->transform);
+        ret = -EINVAL;
+        break;
+    }
+    // TODO: Once we have atomic test, this should fall back to GL
+    if (rotation && plane->rotation_property().id() == 0) {
+      ALOGE("Rotation is not supported on plane %d", plane->id());
+      ret = -EINVAL;
+      break;
+    }
+
     ret =
         drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
                               crtc->id()) ||
@@ -202,6 +235,16 @@
       ALOGE("Failed to add plane %d to set", plane->id());
       break;
     }
+
+    if (plane->rotation_property().id()) {
+      ret = drmModePropertySetAdd(
+              pset, plane->id(), plane->rotation_property().id(), rotation);
+      if (ret) {
+        ALOGE("Failed to add rotation property %d to plane %d",
+              plane->rotation_property().id(), plane->id());
+        break;
+      }
+    }
   }
 
   if (!ret) {
@@ -257,22 +300,22 @@
   }
 
   switch (composition->type()) {
-  case DRM_COMPOSITION_TYPE_FRAME:
-    ret = ApplyFrame(composition.get());
-    if (ret) {
-      ALOGE("Composite failed for display %d", display_);
+    case DRM_COMPOSITION_TYPE_FRAME:
+      ret = ApplyFrame(composition.get());
+      if (ret) {
+        ALOGE("Composite failed for display %d", display_);
+        return ret;
+      }
+      ++dump_frames_composited_;
+      break;
+    case DRM_COMPOSITION_TYPE_DPMS:
+      ret = ApplyDpms(composition.get());
+      if (ret)
+        ALOGE("Failed to apply dpms for display %d", display_);
       return ret;
-    }
-    ++dump_frames_composited_;
-    break;
-  case DRM_COMPOSITION_TYPE_DPMS:
-    ret = ApplyDpms(composition.get());
-    if (ret)
-      ALOGE("Failed to apply dpms for display %d", display_);
-    return ret;
-  default:
-    ALOGE("Unknown composition type %d", composition->type());
-    return -EINVAL;
+    default:
+      ALOGE("Unknown composition type %d", composition->type());
+      return -EINVAL;
   }
 
   if (active_composition_)
@@ -364,7 +407,8 @@
         " src[x/y/w/h]=" << layer->sourceCropf.left << "/" <<
         layer->sourceCropf.top << "/" <<
         layer->sourceCropf.right - layer->sourceCropf.left << "/" <<
-        layer->sourceCropf.bottom - layer->sourceCropf.top << "\n";
+        layer->sourceCropf.bottom - layer->sourceCropf.top <<  " transform=" <<
+        layer->transform << "\n";
   }
 
 }
diff --git a/drmplane.cpp b/drmplane.cpp
index d6ac875..3f17d7c 100644
--- a/drmplane.cpp
+++ b/drmplane.cpp
@@ -120,6 +120,10 @@
     return ret;
   }
 
+  ret = drm_->GetPlaneProperty(*this, "rotation", &rotation_property_);
+  if (ret)
+    ALOGE("Could not get rotation property");
+
   return 0;
 }
 
@@ -174,4 +178,8 @@
 const DrmProperty &DrmPlane::src_h_property() const {
   return src_h_property_;
 }
+
+const DrmProperty &DrmPlane::rotation_property() const {
+  return rotation_property_;
+}
 }
diff --git a/drmplane.h b/drmplane.h
index 96cd85c..1969d52 100644
--- a/drmplane.h
+++ b/drmplane.h
@@ -51,6 +51,7 @@
   const DrmProperty &src_y_property() const;
   const DrmProperty &src_w_property() const;
   const DrmProperty &src_h_property() const;
+  const DrmProperty &rotation_property() const;
 
  private:
   DrmPlane(const DrmPlane &);
@@ -72,6 +73,7 @@
   DrmProperty src_y_property_;
   DrmProperty src_w_property_;
   DrmProperty src_h_property_;
+  DrmProperty rotation_property_;
 };
 }
 
diff --git a/glworker.cpp b/glworker.cpp
index e093a73..c737c45 100644
--- a/glworker.cpp
+++ b/glworker.cpp
@@ -453,11 +453,11 @@
   return 0;
 }
 
-GLWorker::Compositor::Compositor()
+GLWorkerCompositor::GLWorkerCompositor()
     : egl_display_(EGL_NO_DISPLAY), egl_ctx_(EGL_NO_CONTEXT) {
 }
 
-int GLWorker::Compositor::Init() {
+int GLWorkerCompositor::Init() {
   int ret = 0;
   const char *egl_extensions;
   const char *gl_extensions;
@@ -548,14 +548,14 @@
   return 0;
 }
 
-GLWorker::Compositor::~Compositor() {
+GLWorkerCompositor::~GLWorkerCompositor() {
   if (egl_display_ != EGL_NO_DISPLAY && egl_ctx_ != EGL_NO_CONTEXT)
     if (eglDestroyContext(egl_display_, egl_ctx_) == EGL_FALSE)
       ALOGE("Failed to destroy OpenGL ES Context: %s", GetEGLError());
 }
 
-int GLWorker::Compositor::Composite(hwc_layer_1 *layers, size_t num_layers,
-                                    sp<GraphicBuffer> framebuffer) {
+int GLWorkerCompositor::Composite(hwc_layer_1 *layers, size_t num_layers,
+                                  sp<GraphicBuffer> framebuffer) {
   ATRACE_CALL();
   int ret = 0;
   size_t i;
@@ -702,7 +702,7 @@
   return ret;
 }
 
-int GLWorker::DoComposition(Compositor &compositor, Work *work) {
+int GLWorker::DoComposition(GLWorkerCompositor &compositor, Work *work) {
   int ret =
       compositor.Composite(work->layers, work->num_layers, work->framebuffer);
 
@@ -848,7 +848,7 @@
 
   TRY(pthread_mutex_lock(&lock_), "lock GLThread", return );
 
-  Compositor compositor;
+  GLWorkerCompositor compositor;
 
   TRY(compositor.Init(), "initialize GL", goto out_signal_done);
 
diff --git a/glworker.h b/glworker.h
index 4ac0e7d..e9febec 100644
--- a/glworker.h
+++ b/glworker.h
@@ -30,6 +30,8 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include <ui/GraphicBuffer.h>
+
 struct hwc_layer_1;
 
 namespace android {
@@ -77,6 +79,24 @@
   }
 };
 
+class GLWorkerCompositor {
+ public:
+  GLWorkerCompositor();
+  ~GLWorkerCompositor();
+
+  int Init();
+
+  int Composite(hwc_layer_1 *layers, size_t num_layers,
+                sp<GraphicBuffer> framebuffer);
+
+ private:
+  EGLDisplay egl_display_;
+  EGLContext egl_ctx_;
+
+  std::vector<AutoGLProgram> blend_programs_;
+  AutoGLBuffer vertex_buffer_;
+};
+
 class GLWorker {
  public:
   struct Work {
@@ -89,24 +109,6 @@
     Work(const Work &rhs) = delete;
   };
 
-  class Compositor {
-   public:
-    Compositor();
-    ~Compositor();
-
-    int Init();
-
-    int Composite(hwc_layer_1 *layers, size_t num_layers,
-                  sp<GraphicBuffer> framebuffer);
-
-   private:
-    EGLDisplay egl_display_;
-    EGLContext egl_ctx_;
-
-    std::vector<AutoGLProgram> blend_programs_;
-    AutoGLBuffer vertex_buffer_;
-  };
-
   GLWorker();
   ~GLWorker();
 
@@ -126,7 +128,7 @@
   int worker_ret_;
 
   void WorkerRoutine();
-  int DoComposition(Compositor &compositor, Work *work);
+  int DoComposition(GLWorkerCompositor &compositor, Work *work);
 
   int SignalWorker(Work *work, bool worker_exit);