OSDN Git Service

Move all display transform checks to PlaneState.
authorKalyan Kondapally <kalyan.kondapally@intel.com>
Sun, 14 Jan 2018 11:23:23 +0000 (03:23 -0800)
committerKalyan Kondapally <kalyan.kondapally@intel.com>
Sun, 14 Jan 2018 20:34:02 +0000 (12:34 -0800)
This should given us ability to check if rotation can be
supported by individual layers or offscreen surface of an
plane. This should ensure we are able to validate the
support propertly before trying to use the display capabilities
or fall back to handle the rotation with 3D Compositor.

Jira: None.
Test: 180 rotation works as before.
Signed-off-by: Kalyan Kondapally <kalyan.kondapally@intel.com>
18 files changed:
common/compositor/compositor.cpp
common/compositor/compositor.h
common/compositor/nativesurface.cpp
common/compositor/nativesurface.h
common/compositor/renderstate.cpp
common/compositor/renderstate.h
common/core/overlaylayer.cpp
common/core/overlaylayer.h
common/display/displayplanemanager.cpp
common/display/displayplanemanager.h
common/display/displayplanestate.cpp
common/display/displayplanestate.h
common/display/displayqueue.cpp
common/display/displayqueue.h
common/display/virtualdisplay.cpp
wsi/displayplane.h
wsi/drm/drmplane.cpp
wsi/drm/drmplane.h

index a1d7202..d050fcd 100644 (file)
@@ -107,8 +107,15 @@ bool Compositor::Draw(DisplayPlaneStateList &comp_planes,
       state.surface_ = surface;
       size_t num_regions = comp_regions.size();
       state.states_.reserve(num_regions);
+      bool use_plane_transform = false;
+      if (plane.GetRotationType() ==
+          DisplayPlaneState::RotationType::kGPURotation) {
+        use_plane_transform = true;
+      }
+
       if (!CalculateRenderState(layers, comp_regions, state,
-                                plane.IsUsingPlaneScalar())) {
+                                plane.IsUsingPlaneScalar(),
+                                use_plane_transform)) {
         ETRACE("Failed to calculate Render state.");
         return false;
       }
@@ -184,13 +191,14 @@ void Compositor::FreeResources() {
 bool Compositor::CalculateRenderState(
     std::vector<OverlayLayer> &layers,
     const std::vector<CompositionRegion> &comp_regions, DrawState &draw_state,
-    bool uses_display_up_scaling) {
+    bool uses_display_up_scaling, bool use_plane_transform) {
   CTRACE();
   size_t num_regions = comp_regions.size();
   for (size_t region_index = 0; region_index < num_regions; region_index++) {
     const CompositionRegion &region = comp_regions.at(region_index);
     RenderState state;
-    state.ConstructState(layers, region, uses_display_up_scaling);
+    state.ConstructState(layers, region, uses_display_up_scaling,
+                         use_plane_transform);
     if (state.layer_state_.empty()) {
       continue;
     }
index 6cfa15b..b8d6522 100644 (file)
@@ -63,7 +63,8 @@ class Compositor {
  private:
   bool CalculateRenderState(std::vector<OverlayLayer> &layers,
                             const std::vector<CompositionRegion> &comp_regions,
-                            DrawState &state, bool uses_display_up_scaling);
+                            DrawState &state, bool uses_display_up_scaling,
+                            bool use_plane_transform = false);
   void SeparateLayers(const std::vector<size_t> &dedicated_layers,
                       const std::vector<size_t> &source_layers,
                       const std::vector<HwcRect<int>> &display_frame,
index 81fa23b..cec1d7c 100644 (file)
@@ -77,8 +77,8 @@ void NativeSurface::SetClearSurface(ClearType clear_surface) {
   clear_surface_ = clear_surface;
 }
 
-void NativeSurface::SetDisplayRotation(HWCRotation rotation) {
-  layer_.SetDisplayRotation(rotation);
+void NativeSurface::SetTransform(uint32_t transform) {
+  layer_.SetTransform(transform);
 }
 
 void NativeSurface::SetSurfaceAge(uint32_t value) {
index dca07b6..feb80b9 100644 (file)
@@ -112,8 +112,8 @@ class NativeSurface {
     return surface_damage_;
   }
 
-  // Rotates this surface to rotation.
-  void SetDisplayRotation(HWCRotation rotation);
+  // Applies rotation transform to this surface.
+  void SetTransform(uint32_t transform);
 
  protected:
   OverlayLayer layer_;
@@ -127,7 +127,6 @@ class NativeSurface {
   bool in_use_;
   ClearType clear_surface_;
   uint32_t surface_age_;
-  HWCRotation rotation_ = kRotateNone;
   HwcRect<int> surface_damage_;
   HwcRect<int> last_surface_damage_;
 };
index c43d1f0..a9a4f1f 100644 (file)
@@ -27,7 +27,8 @@ namespace hwcomposer {
 
 void RenderState::ConstructState(std::vector<OverlayLayer> &layers,
                                  const CompositionRegion &region,
-                                 bool uses_display_up_scaling) {
+                                 bool uses_display_up_scaling,
+                                 bool use_plane_transform) {
   float bounds[4];
   std::copy_n(region.frame.bounds, 4, bounds);
   x_ = bounds[0];
@@ -47,7 +48,12 @@ void RenderState::ConstructState(std::vector<OverlayLayer> &layers,
     src.layer_index_ = texture_index;
     bool swap_xy = false;
     bool flip_xy[2] = {false, false};
-    switch (layer.GetTransform()) {
+    uint32_t transform = layer.GetTransform();
+    if (use_plane_transform) {
+      transform = layer.GetPlaneTransform();
+    }
+
+    switch (transform) {
       case HWCTransform::kTransform180: {
         swap_xy = false;
         flip_xy[0] = true;
@@ -62,10 +68,10 @@ void RenderState::ConstructState(std::vector<OverlayLayer> &layers,
       }
       case HWCTransform::kTransform90: {
         swap_xy = true;
-        if (layer.GetTransform() & HWCTransform::kReflectX) {
+        if (transform & HWCTransform::kReflectX) {
           flip_xy[0] = true;
           flip_xy[1] = true;
-        } else if (layer.GetTransform() & HWCTransform::kReflectY) {
+        } else if (transform & HWCTransform::kReflectY) {
           flip_xy[0] = false;
           flip_xy[1] = false;
         } else {
index aa4046e..a44af70 100644 (file)
@@ -45,7 +45,7 @@ struct RenderState {
 
   void ConstructState(std::vector<OverlayLayer> &layers,
                       const CompositionRegion &region,
-                      bool uses_display_up_scaling);
+                      bool uses_display_up_scaling, bool use_plane_transform);
 
   uint32_t x_;
   uint32_t y_;
index 9ebbb13..34fd37d 100644 (file)
@@ -105,21 +105,22 @@ void OverlayLayer::SetDisplayFrame(const HwcRect<int>& display_frame) {
   surface_damage_ = display_frame;
 }
 
-void OverlayLayer::SetDisplayRotation(HWCRotation rotation) {
-  ValidateTransform(transform_, rotation);
+void OverlayLayer::SetTransform(uint32_t transform) {
+  plane_transform_ = transform;
+  transform_ = transform;
 }
 
 void OverlayLayer::ValidateTransform(uint32_t transform,
                                      uint32_t display_transform) {
   if (transform & kTransform90) {
     switch (display_transform) {
-      case kRotate90:
+      case HWCTransform::kTransform90:
         plane_transform_ |= kTransform180;
         break;
-      case kRotate180:
+      case HWCTransform::kTransform180:
         plane_transform_ |= kTransform270;
         break;
-      case kRotateNone:
+      case HWCTransform::kIdentity:
         plane_transform_ |= kTransform90;
         if (transform & kReflectX) {
           plane_transform_ |= kReflectX;
@@ -134,13 +135,13 @@ void OverlayLayer::ValidateTransform(uint32_t transform,
     }
   } else if (transform & kTransform180) {
     switch (display_transform) {
-      case kRotate90:
+      case HWCTransform::kTransform90:
         plane_transform_ |= kTransform270;
         break;
-      case kRotate270:
+      case HWCTransform::kTransform270:
         plane_transform_ |= kTransform90;
         break;
-      case kRotateNone:
+      case HWCTransform::kIdentity:
         plane_transform_ |= kTransform180;
         break;
       default:
@@ -148,20 +149,20 @@ void OverlayLayer::ValidateTransform(uint32_t transform,
     }
   } else if (transform & kTransform270) {
     switch (display_transform) {
-      case kRotate270:
+      case HWCTransform::kTransform270:
         plane_transform_ |= kTransform180;
         break;
-      case kRotate180:
+      case HWCTransform::kTransform180:
         plane_transform_ |= kTransform90;
         break;
-      case kRotateNone:
+      case HWCTransform::kIdentity:
         plane_transform_ |= kTransform270;
         break;
       default:
         break;
     }
   } else {
-    if (display_transform == kRotate90) {
+    if (display_transform & HWCTransform::kTransform90) {
       if (transform & kReflectX) {
         plane_transform_ |= kReflectX;
       }
@@ -173,10 +174,10 @@ void OverlayLayer::ValidateTransform(uint32_t transform,
       plane_transform_ |= kTransform90;
     } else {
       switch (display_transform) {
-        case kRotate270:
+        case HWCTransform::kTransform270:
           plane_transform_ |= kTransform270;
           break;
-        case kRotate180:
+        case HWCTransform::kTransform180:
           plane_transform_ |= kTransform180;
           break;
         default:
@@ -190,12 +191,11 @@ void OverlayLayer::InitializeState(HwcLayer* layer,
                                    ResourceManager* resource_manager,
                                    OverlayLayer* previous_layer,
                                    uint32_t z_order, uint32_t layer_index,
-                                   uint32_t max_height, HWCRotation rotation,
+                                   uint32_t max_height, uint32_t rotation,
                                    bool handle_constraints) {
   transform_ = layer->GetTransform();
   if (rotation != kRotateNone) {
     ValidateTransform(layer->GetTransform(), rotation);
-    transform_ = plane_transform_;
   } else {
     plane_transform_ = transform_;
   }
@@ -305,7 +305,7 @@ void OverlayLayer::InitializeState(HwcLayer* layer,
 void OverlayLayer::InitializeFromHwcLayer(
     HwcLayer* layer, ResourceManager* resource_manager,
     OverlayLayer* previous_layer, uint32_t z_order, uint32_t layer_index,
-    uint32_t max_height, HWCRotation rotation, bool handle_constraints) {
+    uint32_t max_height, uint32_t rotation, bool handle_constraints) {
   display_frame_width_ = layer->GetDisplayFrameWidth();
   display_frame_height_ = layer->GetDisplayFrameHeight();
   display_frame_ = layer->GetDisplayFrame();
@@ -316,8 +316,8 @@ void OverlayLayer::InitializeFromHwcLayer(
 void OverlayLayer::InitializeFromScaledHwcLayer(
     HwcLayer* layer, ResourceManager* resource_manager,
     OverlayLayer* previous_layer, uint32_t z_order, uint32_t layer_index,
-    const HwcRect<int>& display_frame, uint32_t max_height,
-    HWCRotation rotation, bool handle_constraints) {
+    const HwcRect<int>& display_frame, uint32_t max_height, uint32_t rotation,
+    bool handle_constraints) {
   SetDisplayFrame(display_frame);
   InitializeState(layer, resource_manager, previous_layer, z_order, layer_index,
                   max_height, rotation, handle_constraints);
index a5c0dda..08a35fc 100644 (file)
@@ -49,14 +49,14 @@ struct OverlayLayer {
   void InitializeFromHwcLayer(HwcLayer* layer, ResourceManager* buffer_manager,
                               OverlayLayer* previous_layer, uint32_t z_order,
                               uint32_t layer_index, uint32_t max_height,
-                              HWCRotation rotation, bool handle_constraints);
+                              uint32_t rotation, bool handle_constraints);
 
   void InitializeFromScaledHwcLayer(HwcLayer* layer,
                                     ResourceManager* buffer_manager,
                                     OverlayLayer* previous_layer,
                                     uint32_t z_order, uint32_t layer_index,
                                     const HwcRect<int>& display_frame,
-                                    uint32_t max_height, HWCRotation rotation,
+                                    uint32_t max_height, uint32_t rotation,
                                     bool handle_constraints);
   // Get z order of this layer.
   uint32_t GetZorder() const {
@@ -79,6 +79,10 @@ struct OverlayLayer {
     return blending_;
   }
 
+  // This represents the transform to
+  // be applied to this layer without taking
+  // into account any Display transform i.e.
+  // GetPlaneTransform()
   uint32_t GetTransform() const {
     return transform_;
   }
@@ -91,8 +95,8 @@ struct OverlayLayer {
     return plane_transform_;
   }
 
-  // Rotates this layer to rotation.
-  void SetDisplayRotation(HWCRotation rotation);
+  // Applies transform to this layer before scanout.
+  void SetTransform(uint32_t transform);
 
   OverlayBuffer* GetBuffer() const;
 
@@ -230,7 +234,7 @@ struct OverlayLayer {
   void InitializeState(HwcLayer* layer, ResourceManager* buffer_manager,
                        OverlayLayer* previous_layer, uint32_t z_order,
                        uint32_t layer_index, uint32_t max_height,
-                       HWCRotation rotation, bool handle_constraints);
+                       uint32_t rotation, bool handle_constraints);
 
   uint32_t transform_ = 0;
   uint32_t plane_transform_ = 0;
index 574dc1c..65b4d33 100644 (file)
@@ -180,7 +180,8 @@ bool DisplayPlaneManager::ValidateLayers(
         validate_final_layers = false;
         test_commit_done = true;
         if (!fall_back || prefer_seperate_plane) {
-          composition.emplace_back(plane, layer, layer->GetZorder());
+          composition.emplace_back(plane, layer, layer->GetZorder(),
+                                   display_transform_);
 #ifdef SURFACE_TRACING
           ISURFACETRACE("Added Layer for direct Scanout: %d \n",
                         layer->GetZorder());
@@ -198,13 +199,38 @@ bool DisplayPlaneManager::ValidateLayers(
           break;
         } else {
           if (composition.empty()) {
-            // If we are here, it means the layer failed with
-            // Primary. Let's force GPU for all layers.
-            // FIXME: We should try to use overlay for
-            // other layers in this case.
-            ForceGpuForAllLayers(commit_planes, composition, layers, mark_later,
-                                 false);
-            return true;
+            bool force_all_layers = true;
+            if (display_transform_ != kIdentity) {
+              composition.emplace_back(plane, layer, layer->GetZorder(),
+                                       display_transform_);
+              DisplayPlaneState &last_plane = composition.back();
+              ResetPlaneTarget(last_plane, commit_planes.back());
+              // If DisplayTransform is not supported, let's check if
+              // we can fallback to GPU rotation for this plane.
+              if (last_plane.GetRotationType() ==
+                  DisplayPlaneState::RotationType::kDisplayRotation) {
+                last_plane.SetRotationType(
+                    DisplayPlaneState::RotationType::kGPURotation, false);
+
+                // Check if we can rotate using Display plane.
+                if (!FallbacktoGPU(last_plane.GetDisplayPlane(),
+                                   last_plane.GetOffScreenTarget()->GetLayer(),
+                                   commit_planes)) {
+                  force_all_layers = false;
+                  validate_final_layers = true;
+                }
+              }
+            }
+
+            if (force_all_layers) {
+              // If we are here, it means the layer failed with
+              // Primary. Let's force GPU for all layers.
+              // FIXME: We should try to use overlay for
+              // other layers in this case.
+              ForceGpuForAllLayers(commit_planes, composition, layers,
+                                   mark_later, false);
+              return true;
+            }
           } else {
             commit_planes.pop_back();
             DisplayPlaneState &last_plane = composition.back();
@@ -218,6 +244,8 @@ bool DisplayPlaneManager::ValidateLayers(
             } else if (add_index > 0) {
               SwapSurfaceIfNeeded(&last_plane);
             }
+
+            ValidateForDisplayTransform(last_plane, commit_planes);
           }
         }
       }
@@ -265,6 +293,7 @@ bool DisplayPlaneManager::ValidateLayers(
         }
 
         commit_planes.back().layer = last_plane.GetOverlayLayer();
+        ValidateForDisplayTransform(last_plane, commit_planes);
       }
     }
   }
@@ -295,12 +324,12 @@ bool DisplayPlaneManager::ValidateLayers(
   for (DisplayPlaneState &plane : composition) {
     if (plane.NeedsOffScreenComposition()) {
       plane.RefreshSurfacesIfNeeded();
+      plane.ValidateReValidation();
       if (!render_layers) {
         render_layers = !plane.SurfaceRecycled();
       }
 
-      render_layers = true;
-      if (plane.IsRevalidationNeeded() !=
+      if (plane.RevalidationType() !=
           DisplayPlaneState::ReValidationType::kNone) {
         re_validation = true;
       }
@@ -473,8 +502,10 @@ void DisplayPlaneManager::ValidateCursorLayer(
       }
 
       last_plane->UsePlaneScalar(false);
+      ValidateForDisplayTransform(*last_plane, commit_planes);
     } else {
-      composition.emplace_back(plane, cursor_layer, cursor_layer->GetZorder());
+      composition.emplace_back(plane, cursor_layer, cursor_layer->GetZorder(),
+                               display_transform_);
 #ifdef SURFACE_TRACING
       ISURFACETRACE("Added CursorLayer for direct scanout: %d \n",
                     cursor_layer->GetZorder());
@@ -513,6 +544,35 @@ void DisplayPlaneManager::ValidateCursorLayer(
     PreparePlaneForCursor(last_plane, mark_later, validate_final_layers,
                           is_video, recycle_resources);
     last_plane->UsePlaneScalar(false);
+    ValidateForDisplayTransform(*last_plane, commit_planes);
+  }
+}
+
+void DisplayPlaneManager::ValidateForDisplayTransform(
+    DisplayPlaneState &last_plane,
+    const std::vector<OverlayPlane> &commit_planes) const {
+  if (display_transform_ != kIdentity) {
+    // No need for any check if we are relying on rotation during
+    // 3D Composition pass.
+    if (last_plane.GetRotationType() ==
+        DisplayPlaneState::RotationType::kGPURotation) {
+      return;
+    }
+
+    last_plane.ValidateReValidation();
+    if (last_plane.RevalidationType() &
+        DisplayPlaneState::ReValidationType::kRotation) {
+      uint32_t validation_done = DisplayPlaneState::ReValidationType::kRotation;
+      // Ensure Rotation doesn't impact the results.
+      if (FallbacktoGPU(last_plane.GetDisplayPlane(),
+                        last_plane.GetOffScreenTarget()->GetLayer(),
+                        commit_planes)) {
+        last_plane.SetRotationType(
+            DisplayPlaneState::RotationType::kGPURotation, false);
+      }
+
+      last_plane.RevalidationDone(validation_done);
+    }
   }
 }
 
@@ -528,7 +588,7 @@ void DisplayPlaneManager::ValidateForDisplayScaling(
   // If we are here this means the layer cannot be scaled using display, just
   // return.
   if (!ignore_format &&
-      (current_layer->GetPlaneTransform() == HWCTransform::kIdentity) &&
+      (current_layer->GetTransform() == HWCTransform::kIdentity) &&
       last_plane.GetDisplayPlane()->IsSupportedFormat(
           current_layer->GetBuffer()->GetFormat())) {
     return;
@@ -586,8 +646,8 @@ void DisplayPlaneManager::ReleaseFreeOffScreenTargets() {
   surfaces.swap(surfaces_);
 }
 
-void DisplayPlaneManager::SetDisplayRotation(HWCRotation rotation) {
-  rotation_ = rotation;
+void DisplayPlaneManager::SetDisplayTransform(uint32_t transform) {
+  display_transform_ = transform;
 }
 
 void DisplayPlaneManager::EnsureOffScreenTarget(DisplayPlaneState &plane) {
@@ -626,9 +686,6 @@ void DisplayPlaneManager::EnsureOffScreenTarget(DisplayPlaneState &plane) {
   }
 
   surface->SetPlaneTarget(plane, gpu_fd_);
-  if (rotation_ != kRotateNone)
-    surface->SetDisplayRotation(rotation_);
-
   plane.SetOffScreenTarget(surface);
 }
 
@@ -707,7 +764,7 @@ void DisplayPlaneManager::ForceGpuForAllLayers(
   DisplayPlane *current_plane = overlay_planes_.at(0).get();
 
   composition.emplace_back(current_plane, primary_layer,
-                           primary_layer->GetZorder());
+                           primary_layer->GetZorder(), display_transform_);
   DisplayPlaneState &last_plane = composition.back();
   last_plane.ForceGPURendering();
   layer_begin++;
@@ -801,8 +858,16 @@ bool DisplayPlaneManager::ReValidatePlanes(
       continue;
     }
 
-    if (last_plane.IsRevalidationNeeded() ==
-        DisplayPlaneState::ReValidationType::kScanout) {
+    uint32_t revalidation_type = last_plane.RevalidationType();
+
+    if (!revalidation_type) {
+      render = true;
+      index++;
+      continue;
+    }
+
+    uint32_t validation_done = DisplayPlaneState::ReValidationType::kScanout;
+    if (revalidation_type & DisplayPlaneState::ReValidationType::kScanout) {
       const std::vector<size_t> &source_layers = last_plane.GetSourceLayers();
       bool uses_scalar = last_plane.IsUsingPlaneScalar();
       // Store current layer to re-set in case commit fails.
@@ -832,16 +897,45 @@ bool DisplayPlaneManager::ReValidatePlanes(
 #endif
         MarkSurfacesForRecycling(&last_plane, mark_later, false);
       }
-    } else if (last_plane.IsRevalidationNeeded() ==
-               DisplayPlaneState::ReValidationType::kScalar) {
+    }
+
+    render = true;
+    index++;
+    if (revalidation_type & DisplayPlaneState::ReValidationType::kScalar) {
       ValidateForDisplayScaling(last_plane, commit_planes,
                                 last_plane.GetOffScreenTarget()->GetLayer(),
                                 true);
+      validation_done |= DisplayPlaneState::ReValidationType::kScalar;
     }
 
-    render = true;
-    last_plane.RevalidationDone();
-    index++;
+    if (revalidation_type & DisplayPlaneState::ReValidationType::kRotation) {
+      validation_done |= DisplayPlaneState::ReValidationType::kRotation;
+      // Save old rotation type.
+      DisplayPlaneState::RotationType old_type = last_plane.GetRotationType();
+      DisplayPlaneState::RotationType new_type = old_type;
+      if (old_type == DisplayPlaneState::RotationType::kGPURotation) {
+        last_plane.SetRotationType(
+            DisplayPlaneState::RotationType::kDisplayRotation, false);
+      } else if (re_validate_commit) {
+        // We should have already done a full commit check above.
+        // As their is no state change we can avoid another test
+        // commit here.
+        last_plane.RevalidationDone(validation_done);
+        continue;
+      }
+
+      // Check if we can rotate using Display plane.
+      if (FallbacktoGPU(last_plane.GetDisplayPlane(),
+                        last_plane.GetOffScreenTarget()->GetLayer(),
+                        commit_planes)) {
+        new_type = DisplayPlaneState::RotationType::kGPURotation;
+      }
+
+      // Set new rotation type. Clear surfaces in case type has changed.
+      last_plane.SetRotationType(new_type, new_type != old_type);
+    }
+
+    last_plane.RevalidationDone(validation_done);
   }
 
   return render;
index e522dae..6659431 100644 (file)
@@ -82,9 +82,9 @@ class DisplayPlaneManager {
     return height_;
   }
 
-  // This is the rotation to which physical pipe
-  // associated with this plane manager is rotated.
-  void SetDisplayRotation(HWCRotation rotation);
+  // Transform to be applied to all planes associated
+  // with pipe of this displayplanemanager.
+  void SetDisplayTransform(uint32_t transform);
 
  private:
   struct LayerResultCache {
@@ -117,6 +117,10 @@ class DisplayPlaneManager {
                                  OverlayLayer *current_layer,
                                  bool ignore_format = false);
 
+  void ValidateForDisplayTransform(
+      DisplayPlaneState &last_plane,
+      const std::vector<OverlayPlane> &commit_planes) const;
+
   void ForceGpuForAllLayers(std::vector<OverlayPlane> &commit_planes,
                             DisplayPlaneStateList &composition,
                             std::vector<OverlayLayer> &layers,
@@ -145,7 +149,7 @@ class DisplayPlaneManager {
   uint32_t width_;
   uint32_t height_;
   uint32_t gpu_fd_;
-  HWCRotation rotation_ = kRotateNone;
+  uint32_t display_transform_ = kIdentity;
 };
 
 }  // namespace hwcomposer
index f14c997..40051a4 100644 (file)
 namespace hwcomposer {
 
 DisplayPlaneState::DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer,
-                                     uint32_t index) {
+                                     uint32_t index, uint32_t plane_transform) {
   private_data_ = std::make_shared<DisplayPlanePrivateState>();
   private_data_->source_layers_.emplace_back(index);
   private_data_->display_frame_ = layer->GetDisplayFrame();
-  private_data_->check_display_scalar_ = true;
+  private_data_->rect_updated_ = true;
   private_data_->source_crop_ = layer->GetSourceCrop();
   if (layer->IsCursorLayer()) {
     private_data_->type_ = DisplayPlanePrivateState::PlaneType::kCursor;
@@ -34,6 +34,14 @@ DisplayPlaneState::DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer,
   plane->SetInUse(true);
   private_data_->plane_ = plane;
   private_data_->layer_ = layer;
+  private_data_->plane_transform_ = plane_transform;
+  if (!private_data_->plane_->IsSupportedTransform(plane_transform)) {
+    private_data_->rotation_type_ =
+        DisplayPlaneState::RotationType::kGPURotation;
+    private_data_->unsupported_siplay_rotation_ = true;
+  } else {
+    private_data_->rotation_type_ = RotationType::kDisplayRotation;
+  }
 }
 
 void DisplayPlaneState::CopyState(DisplayPlaneState &state) {
@@ -52,7 +60,7 @@ const HwcRect<float> &DisplayPlaneState::GetSourceCrop() const {
 
 void DisplayPlaneState::AddLayer(const OverlayLayer *layer) {
   const HwcRect<int> &display_frame = layer->GetDisplayFrame();
-  HwcRect<int> &target_display_frame = private_data_->display_frame_;
+  HwcRect<int> target_display_frame = private_data_->display_frame_;
   target_display_frame.left =
       std::min(target_display_frame.left, display_frame.left);
   target_display_frame.top =
@@ -62,7 +70,7 @@ void DisplayPlaneState::AddLayer(const OverlayLayer *layer) {
   target_display_frame.bottom =
       std::max(target_display_frame.bottom, display_frame.bottom);
 
-  HwcRect<float> &target_source_crop = private_data_->source_crop_;
+  HwcRect<float> target_source_crop = private_data_->source_crop_;
   const HwcRect<float> &source_crop = layer->GetSourceCrop();
   target_source_crop.left = std::min(target_source_crop.left, source_crop.left);
   target_source_crop.top = std::min(target_source_crop.top, source_crop.top);
@@ -75,6 +83,22 @@ void DisplayPlaneState::AddLayer(const OverlayLayer *layer) {
 
   private_data_->state_ = DisplayPlanePrivateState::State::kRender;
 
+  // If layers are less than 2, we need to enforce rect checks as
+  // we shouldn't have done them yet (i.e. Previous state could have
+  // been direct scanout.)
+  bool rect_updated = true;
+  if (private_data_->source_layers_.size() > 2 &&
+      (private_data_->display_frame_ == target_display_frame) &&
+      ((private_data_->source_crop_ == target_source_crop))) {
+    rect_updated = false;
+  } else {
+    private_data_->display_frame_ = target_display_frame;
+    private_data_->source_crop_ = target_source_crop;
+  }
+
+  if (!private_data_->rect_updated_)
+    private_data_->rect_updated_ = rect_updated;
+
   if (!private_data_->has_cursor_layer_)
     private_data_->has_cursor_layer_ = layer->IsCursorLayer();
 
@@ -90,8 +114,8 @@ void DisplayPlaneState::AddLayer(const OverlayLayer *layer) {
   }
 
   // Reset Validation state.
-  if (re_validate_layer_ == ReValidationType::kScanout)
-    re_validate_layer_ = ReValidationType::kNone;
+  if (re_validate_layer_ & ReValidationType::kScanout)
+    re_validate_layer_ &= ~ReValidationType::kScanout;
 
   refresh_needed_ = true;
 }
@@ -170,9 +194,17 @@ void DisplayPlaneState::ResetLayers(const std::vector<OverlayLayer> &layers,
 #endif
 
   private_data_->source_layers_.swap(source_layers);
-  private_data_->display_frame_ = target_display_frame;
-  private_data_->source_crop_ = target_source_crop;
-  private_data_->check_display_scalar_ = true;
+  bool rect_updated = true;
+  if ((private_data_->display_frame_ == target_display_frame) &&
+      ((private_data_->source_crop_ == target_source_crop))) {
+    rect_updated = false;
+  } else {
+    private_data_->display_frame_ = target_display_frame;
+    private_data_->source_crop_ = target_source_crop;
+  }
+
+  if (!private_data_->rect_updated_)
+    private_data_->rect_updated_ = rect_updated;
 
   if (private_data_->source_layers_.size() == 1) {
     if (private_data_->has_cursor_layer_) {
@@ -182,6 +214,9 @@ void DisplayPlaneState::ResetLayers(const std::vector<OverlayLayer> &layers,
     } else {
       private_data_->type_ = DisplayPlanePrivateState::PlaneType::kNormal;
     }
+
+    if (!has_video)
+      re_validate_layer_ |= ReValidationType::kScanout;
   } else {
     private_data_->type_ = DisplayPlanePrivateState::PlaneType::kNormal;
   }
@@ -200,7 +235,6 @@ void DisplayPlaneState::UpdateDisplayFrame(const HwcRect<int> &display_frame) {
       std::max(target_display_frame.right, display_frame.right);
   target_display_frame.bottom =
       std::max(target_display_frame.bottom, display_frame.bottom);
-  private_data_->check_display_scalar_ = true;
   refresh_needed_ = true;
 }
 
@@ -212,7 +246,6 @@ void DisplayPlaneState::UpdateSourceCrop(const HwcRect<float> &source_crop) {
       std::max(target_source_crop.right, source_crop.right);
   target_source_crop.bottom =
       std::max(target_source_crop.bottom, source_crop.bottom);
-  private_data_->check_display_scalar_ = true;
   refresh_needed_ = true;
 }
 
@@ -246,6 +279,12 @@ const OverlayLayer *DisplayPlaneState::GetOverlayLayer() const {
 
 void DisplayPlaneState::SetOffScreenTarget(NativeSurface *target) {
   private_data_->layer_ = target->GetLayer();
+  uint32_t rotation = private_data_->plane_transform_;
+  if (private_data_->rotation_type_ != RotationType::kDisplayRotation)
+    rotation = kIdentity;
+
+  target->SetTransform(rotation);
+
   target->ResetDisplayFrame(private_data_->display_frame_);
   if (private_data_->use_plane_scalar_) {
     target->ResetSourceCrop(private_data_->source_crop_);
@@ -434,13 +473,22 @@ bool DisplayPlaneState::NeedsOffScreenComposition() {
   return false;
 }
 
-DisplayPlaneState::ReValidationType DisplayPlaneState::IsRevalidationNeeded()
-    const {
+uint32_t DisplayPlaneState::RevalidationType() const {
   return re_validate_layer_;
 }
 
-void DisplayPlaneState::RevalidationDone() {
-  re_validate_layer_ = ReValidationType::kNone;
+void DisplayPlaneState::RevalidationDone(uint32_t validation_done) {
+  if (validation_done & ReValidationType::kScanout) {
+    re_validate_layer_ &= ~ReValidationType::kScanout;
+  }
+
+  if (validation_done & ReValidationType::kScalar) {
+    re_validate_layer_ &= ~ReValidationType::kScalar;
+  }
+
+  if (validation_done & ReValidationType::kRotation) {
+    re_validate_layer_ &= ~ReValidationType::kRotation;
+  }
 }
 
 bool DisplayPlaneState::CanSquash() const {
@@ -454,13 +502,21 @@ bool DisplayPlaneState::CanSquash() const {
 }
 
 void DisplayPlaneState::ValidateReValidation() {
+  if (!private_data_->rect_updated_)
+    return;
+
+  if (private_data_->plane_transform_ != kIdentity &&
+      !private_data_->unsupported_siplay_rotation_) {
+    re_validate_layer_ |= ReValidationType::kRotation;
+  }
+
   if (private_data_->source_layers_.size() == 1 &&
       !(private_data_->type_ == DisplayPlanePrivateState::PlaneType::kVideo)) {
-    re_validate_layer_ = ReValidationType::kScanout;
+    re_validate_layer_ |= ReValidationType::kScanout;
   } else {
     bool use_scalar = CanUseDisplayUpScaling();
     if (private_data_->use_plane_scalar_ != use_scalar) {
-      re_validate_layer_ = ReValidationType::kScalar;
+      re_validate_layer_ |= ReValidationType::kScalar;
     }
   }
 }
@@ -473,11 +529,10 @@ bool DisplayPlaneState::CanUseDisplayUpScaling() const {
     return false;
   }
 
-  if (!private_data_->check_display_scalar_) {
+  if (!private_data_->rect_updated_) {
     return private_data_->can_use_display_scalar_;
   }
 
-  private_data_->check_display_scalar_ = false;
   const HwcRect<int> &target_display_frame = private_data_->display_frame_;
   const HwcRect<float> &target_src_rect = private_data_->source_crop_;
 
@@ -539,4 +594,30 @@ void DisplayPlaneState::RefreshSurfacesIfNeeded() {
   }
 }
 
+void DisplayPlaneState::SetRotationType(RotationType type, bool refresh) {
+  if (private_data_->rotation_type_ != type) {
+    private_data_->rotation_type_ = type;
+    if (refresh) {
+      refresh_needed_ = true;
+      RefreshSurfaces(NativeSurface::kFullClear);
+    }
+
+    uint32_t rotation = private_data_->plane_transform_;
+    if (type != RotationType::kDisplayRotation)
+      rotation = kIdentity;
+
+    for (NativeSurface *surface : private_data_->surfaces_) {
+      surface->SetTransform(rotation);
+    }
+  }
+}
+
+DisplayPlaneState::RotationType DisplayPlaneState::GetRotationType() const {
+  return private_data_->rotation_type_;
+}
+
+void DisplayPlaneState::PlaneRectUpdated() {
+  private_data_->rect_updated_ = true;
+}
+
 }  // namespace hwcomposer
index 25487a5..40267f9 100644 (file)
@@ -36,15 +36,23 @@ typedef std::vector<DisplayPlaneState> DisplayPlaneStateList;
 
 class DisplayPlaneState {
  public:
-  enum class ReValidationType : int32_t {
-    kNone,     // No Revalidation Needed.
-    kScanout,  // Check if layer can be scanned out directly.
-    kScalar    // Check if layer can use plane scalar.
+  enum ReValidationType {
+    kNone = 0,          // No Revalidation Needed.
+    kScanout = 1 << 0,  // Check if layer can be scanned out directly.
+    kScalar = 1 << 1,   // Check if layer can use plane scalar.
+    kRotation = 1 << 2  // Check if display transform can be supported.
   };
+
+  enum class RotationType : int32_t {
+    kDisplayRotation,  // Plane will be rotated during display composition.
+    kGPURotation       // Plane will be rotated during 3D composition.
+  };
+
   DisplayPlaneState() = default;
   DisplayPlaneState(DisplayPlaneState &&rhs) = default;
   DisplayPlaneState &operator=(DisplayPlaneState &&other) = default;
-  DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer, uint32_t index);
+  DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer, uint32_t index,
+                    uint32_t plane_transform);
 
   // Copies plane state from state.
   void CopyState(DisplayPlaneState &state);
@@ -151,14 +159,14 @@ class DisplayPlaneState {
   // is needed for this plane.
   bool NeedsOffScreenComposition();
 
-  // Returns true if this plane needs to be re-validated
+  // Returns type of validation needed by the plane
   // with current source layer. This will be the case
   // when plane had multiple layers and they where
   // removed leaving it with single layer now.
-  ReValidationType IsRevalidationNeeded() const;
+  uint32_t RevalidationType() const;
 
   // Plane has been revalidated by DisplayPlaneManager.
-  void RevalidationDone();
+  void RevalidationDone(uint32_t validation_done);
 
   // Call this to determine what kind of re-validation
   // is needed by this plane for this frame.
@@ -181,6 +189,19 @@ class DisplayPlaneState {
   // removed.
   void RefreshSurfacesIfNeeded();
 
+  // Set if Plane rotation needs to be handled
+  // using GPU or Display.
+  void SetRotationType(RotationType type, bool refresh);
+
+  // Returns if Plane rotation is handled by
+  // GPU or Display. Return kNone in case
+  // plane is not rotated.
+  RotationType GetRotationType() const;
+
+  // Helper to inform that either Display Frame or
+  // Source rect of this plane has changed.
+  void PlaneRectUpdated();
+
  private:
   class DisplayPlanePrivateState {
    public:
@@ -213,18 +234,23 @@ class DisplayPlaneState {
     bool has_cursor_layer_ = false;
     // Can benefit using display scalar.
     bool can_use_display_scalar_ = false;
-    // Retest for display scalar beenfit.
-    bool check_display_scalar_ = true;
+    // Rects(Either Display Frame/Source Rect) have
+    // changed.
+    bool rect_updated_ = true;
+    // Display cannot support the required rotation.
+    bool unsupported_siplay_rotation_ = false;
     // Any offscreen surfaces used by this
     // plane.
     std::vector<NativeSurface *> surfaces_;
     PlaneType type_ = PlaneType::kNormal;
+    uint32_t plane_transform_ = kIdentity;
+    RotationType rotation_type_ = RotationType::kDisplayRotation;
   };
 
   bool recycled_surface_ = false;
   bool surface_swapped_ = false;
   bool refresh_needed_ = false;
-  ReValidationType re_validate_layer_ = ReValidationType::kNone;
+  uint32_t re_validate_layer_ = ReValidationType::kNone;
   std::shared_ptr<DisplayPlanePrivateState> private_data_;
 };
 
index 12d6ced..8b0a117 100644 (file)
@@ -77,7 +77,7 @@ bool DisplayQueue::Initialize(uint32_t pipe, uint32_t width, uint32_t height,
     return false;
   }
 
-  display_plane_manager_->SetDisplayRotation(plane_rotation_);
+  display_plane_manager_->SetDisplayTransform(plane_transform_);
   ResetQueue();
   vblank_handler_->SetPowerMode(kOff);
   vblank_handler_->Init(gpu_fd_, pipe);
@@ -114,29 +114,20 @@ bool DisplayQueue::SetPowerMode(uint32_t power_mode) {
 
 void DisplayQueue::RotateDisplay(HWCRotation rotation) {
   switch (rotation) {
-    case (kRotateNone):
-      plane_rotation_ = kRotateNone;
-      gl_rotation_ = kRotateNone;
+    case kRotate90:
+      plane_transform_ |= kTransform90;
       break;
-    case (kRotate90):
-      plane_rotation_ = kRotateNone;
-      gl_rotation_ = kRotate90;
+    case kRotate270:
+      plane_transform_ |= kTransform270;
       break;
-    case (kRotate180):
-      plane_rotation_ = kRotate180;
-      gl_rotation_ = kRotateNone;
-      break;
-    case (kRotate270):
-      plane_rotation_ = kRotate270;
-      gl_rotation_ = kRotateNone;
+    case kRotate180:
+      plane_transform_ |= kTransform180;
       break;
     default:
-      plane_rotation_ = kRotateNone;
-      gl_rotation_ = kRotateNone;
       break;
   }
 
-  display_plane_manager_->SetDisplayRotation(plane_rotation_);
+  display_plane_manager_->SetDisplayTransform(plane_transform_);
 }
 
 void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
@@ -198,7 +189,7 @@ void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
 
         last_plane.ValidateReValidation();
 
-        if (last_plane.IsRevalidationNeeded() ==
+        if (last_plane.RevalidationType() &
             DisplayPlaneState::ReValidationType::kScanout) {
           const std::vector<size_t>& source_layers =
               last_plane.GetSourceLayers();
@@ -209,7 +200,8 @@ void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
             plane_validation = true;
           } else if (source_layers.size() == 1) {
             check_to_squash = true;
-            last_plane.RevalidationDone();
+            last_plane.RevalidationDone(
+                DisplayPlaneState::ReValidationType::kScanout);
           }
         }
       }
@@ -223,6 +215,9 @@ void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
         const std::vector<size_t>& source_layers = last_plane.GetSourceLayers();
         size_t layers_size = source_layers.size();
 
+        HwcRect<int> display_frame = last_plane.GetDisplayFrame();
+        HwcRect<float> source_crop = last_plane.GetSourceCrop();
+
         for (size_t i = 0; i < layers_size; i++) {
           const size_t& source_index = source_layers.at(i);
           const OverlayLayer& layer = layers.at(source_index);
@@ -256,10 +251,20 @@ void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
         if (update_rect) {
           content_changed = true;
           last_plane.ValidateReValidation();
-          if (last_plane.IsRevalidationNeeded() !=
+          if (last_plane.RevalidationType() !=
               DisplayPlaneState::ReValidationType::kNone) {
             plane_validation = true;
           }
+
+          bool rect_updated = true;
+          if ((last_plane.GetDisplayFrame() == display_frame) &&
+              (last_plane.GetSourceCrop() == source_crop)) {
+            rect_updated = false;
+          }
+
+          if (rect_updated) {
+            last_plane.PlaneRectUpdated();
+          }
         }
       }
 
@@ -453,12 +458,12 @@ bool DisplayQueue::QueueUpdate(std::vector<HwcLayer*>& source_layers,
 
       overlay_layer->InitializeFromScaledHwcLayer(
           layer, resource_manager_.get(), previous_layer, z_order, layer_index,
-          display_frame, display_plane_manager_->GetHeight(), gl_rotation_,
+          display_frame, display_plane_manager_->GetHeight(), plane_transform_,
           handle_constraints);
     } else {
       overlay_layer->InitializeFromHwcLayer(
           layer, resource_manager_.get(), previous_layer, z_order, layer_index,
-          display_plane_manager_->GetHeight(), gl_rotation_,
+          display_plane_manager_->GetHeight(), plane_transform_,
           handle_constraints);
     }
 
index 0863fc4..aeeb867 100644 (file)
@@ -274,8 +274,7 @@ class DisplayQueue {
   PhysicalDisplay* display_ = NULL;
   SpinLock power_mode_lock_;
   bool handle_display_initializations_ = true;  // to disable hwclock thread.
-  HWCRotation plane_rotation_ = kRotateNone;
-  HWCRotation gl_rotation_ = kRotateNone;
+  uint32_t plane_transform_ = kIdentity;
   SpinLock video_lock_;
   bool requested_video_effect_ = false;
   bool applied_video_effect_ = false;
index 8e77560..809c574 100644 (file)
@@ -106,9 +106,9 @@ bool VirtualDisplay::Present(std::vector<HwcLayer *> &source_layers,
       previous_layer = &(in_flight_layers_.at(z_order));
     }
 
-    overlay_layer.InitializeFromHwcLayer(
-        layer, resource_manager_.get(), previous_layer, z_order, layer_index,
-        width_, kRotateNone, handle_constraints);
+    overlay_layer.InitializeFromHwcLayer(layer, resource_manager_.get(),
+                                         previous_layer, z_order, layer_index,
+                                         width_, kIdentity, handle_constraints);
     index.emplace_back(z_order);
     layers_rects.emplace_back(layer->GetDisplayFrame());
     z_order++;
index 69a68fb..e425811 100644 (file)
@@ -36,6 +36,12 @@ class DisplayPlane {
   virtual bool IsSupportedFormat(uint32_t format) = 0;
 
   /**
+   * API for querying if transform is supported by this
+   * plane.
+   */
+  virtual bool IsSupportedTransform(uint32_t transform) const = 0;
+
+  /**
    * API for querying preferred Video format supported by this
    * plane.
    */
index b0e8c78..5ae04f7 100644 (file)
@@ -32,13 +32,31 @@ DrmPlane::Property::Property() {
 
 bool DrmPlane::Property::Initialize(
     uint32_t fd, const char* name,
-    const ScopedDrmObjectPropertyPtr& plane_props) {
+    const ScopedDrmObjectPropertyPtr& plane_props, uint32_t* rotation) {
   uint32_t count_props = plane_props->count_props;
   for (uint32_t i = 0; i < count_props; i++) {
     ScopedDrmPropertyPtr property(
         drmModeGetProperty(fd, plane_props->props[i]));
     if (property && !strcmp(property->name, name)) {
       id = property->prop_id;
+      if (rotation) {
+        uint32_t temp = 0;
+        for (int enum_index = 0; enum_index < property->count_enums;
+             enum_index++) {
+          struct drm_mode_property_enum* penum = &(property->enums[enum_index]);
+          if (!strcmp(penum->name, "rotate-90")) {
+            temp |= DRM_MODE_ROTATE_90;
+          }
+          if (!strcmp(penum->name, "rotate-180"))
+            temp |= DRM_MODE_ROTATE_180;
+          else if (!strcmp(penum->name, "rotate-270"))
+            temp |= DRM_MODE_ROTATE_270;
+          else if (!strcmp(penum->name, "rotate-0"))
+            temp |= DRM_MODE_ROTATE_0;
+        }
+
+        *rotation = temp;
+      }
       break;
     }
   }
@@ -156,7 +174,7 @@ bool DrmPlane::Initialize(uint32_t gpu_fd,
   if (!ret)
     return false;
 
-  ret = rotation_prop_.Initialize(gpu_fd, "rotation", plane_props);
+  ret = rotation_prop_.Initialize(gpu_fd, "rotation", plane_props, &rotation_);
   if (!ret)
     ETRACE("Could not get rotation property");
 
@@ -349,7 +367,7 @@ bool DrmPlane::ValidateLayer(const OverlayLayer* layer) {
     return false;
   }
 
-  return true;
+  return IsSupportedTransform(transform);
 }
 
 bool DrmPlane::IsSupportedFormat(uint32_t format) {
@@ -366,6 +384,28 @@ bool DrmPlane::IsSupportedFormat(uint32_t format) {
   return false;
 }
 
+bool DrmPlane::IsSupportedTransform(uint32_t transform) const {
+  if (transform & kTransform90) {
+    if (!(rotation_ & DRM_MODE_ROTATE_90)) {
+      return false;
+    }
+  } else if (transform & kTransform180) {
+    if (!(rotation_ & DRM_MODE_ROTATE_180)) {
+      return false;
+    }
+  } else if (transform & kTransform270) {
+    if (!(rotation_ & DRM_MODE_ROTATE_270)) {
+      return false;
+    }
+  } else {
+    if (!(rotation_ & DRM_MODE_ROTATE_0)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 uint32_t DrmPlane::GetPreferredVideoFormat() const {
   return prefered_video_format_;
 }
index 02064c4..6d9e56e 100644 (file)
@@ -59,6 +59,8 @@ class DrmPlane : public DisplayPlane {
 
   bool IsSupportedFormat(uint32_t format) override;
 
+  bool IsSupportedTransform(uint32_t transform) const override;
+
   uint32_t GetPreferredVideoFormat() const override;
   uint32_t GetPreferredFormat() const override;
 
@@ -78,7 +80,8 @@ class DrmPlane : public DisplayPlane {
   struct Property {
     Property();
     bool Initialize(uint32_t fd, const char* name,
-                    const ScopedDrmObjectPropertyPtr& plane_properties);
+                    const ScopedDrmObjectPropertyPtr& plane_properties,
+                    uint32_t* rotation = NULL);
     uint32_t id = 0;
   };
 
@@ -109,6 +112,7 @@ class DrmPlane : public DisplayPlane {
   int32_t kms_fence_ = 0;
   uint32_t prefered_video_format_ = 0;
   uint32_t prefered_format_ = 0;
+  uint32_t rotation_ = 0;
 };
 
 }  // namespace hwcomposer