OSDN Git Service

Add support for using PlaneScalar for Video.
authorKalyan Kondapally <kalyan.kondapally@intel.com>
Sat, 16 Dec 2017 23:57:56 +0000 (15:57 -0800)
committerKalyan Kondapally <kalyan.kondapally@intel.com>
Wed, 20 Dec 2017 23:19:47 +0000 (15:19 -0800)
We can fall back to use our compositor for video layer
for various reasons i.e. Not supported format, video effects
etc. In this case if display frame and source crop are not
same, we scale it today using our Compositor. This patch
adds support to use Plane Scalars as much as possible(when upscaling)
and fall back to current solution in case Display cannot
support it or we need to downscale.

Jira: None.
Test: Check that Video layer is scaled when playing full screen
      and source rect is smaller than display resolution.

Signed-off-by: Kalyan Kondapally <kalyan.kondapally@intel.com>
common/compositor/nativesurface.cpp
common/compositor/va/varenderer.cpp
common/core/overlaylayer.cpp
common/core/overlaylayer.h
common/display/displayplanemanager.cpp
common/display/displayplanemanager.h
common/display/displayplanestate.h
common/display/displayqueue.cpp

index 5f80dc2..c04a8bd 100644 (file)
@@ -90,6 +90,10 @@ void NativeSurface::SetPlaneTarget(DisplayPlaneState &plane, uint32_t gpu_fd) {
   surface_damage_ = display_rect;
   last_surface_damage_ = surface_damage_;
   ResetDisplayFrame(plane.GetDisplayFrame());
+  if (plane.IsVideoPlane()) {
+    layer_.SetSourceCrop(plane.GetSourceCrop());
+  }
+
   plane.SetOverlayLayer(&layer_);
   SetInUse(true);
 
@@ -105,7 +109,9 @@ void NativeSurface::ResetDisplayFrame(const HwcRect<int> &display_frame) {
   surface_damage_ = display_frame;
   last_surface_damage_ = surface_damage_;
   layer_.SetDisplayFrame(display_frame);
-  layer_.SetSourceCrop(HwcRect<float>(display_frame));
+  if (!layer_.IsVideoLayer())
+    layer_.SetSourceCrop(HwcRect<float>(display_frame));
+
   clear_surface_ = true;
 }
 
index a212ab1..bd0b446 100755 (executable)
@@ -258,25 +258,27 @@ bool VARenderer::Draw(const MediaState& state, NativeSurface* surface) {
 
   VARectangle surface_region, output_region;
   const HwcRect<float>& source_crop = state.layer_->GetSourceCrop();
-  surface_region.x = source_crop.left;
-  surface_region.y = source_crop.top;
-  surface_region.width = source_crop.right - source_crop.left;
-  surface_region.height = source_crop.bottom - source_crop.top;
+  surface_region.x = static_cast<int>(source_crop.left);
+  surface_region.y = static_cast<int>(source_crop.top);
+  surface_region.width = static_cast<int>(source_crop.right - source_crop.left);
+  surface_region.height =
+      static_cast<int>(source_crop.bottom - source_crop.top);
   param.surface_region = &surface_region;
 
-  const HwcRect<int>& display_frame = state.layer_->GetDisplayFrame();
-  output_region.x = display_frame.left;
-  output_region.y = display_frame.top;
-  output_region.width = display_frame.right - display_frame.left;
-  output_region.height = display_frame.bottom - display_frame.top;
+  const HwcRect<float>& target_source_rect =
+      surface->GetLayer()->GetSourceCrop();
+  output_region.x = static_cast<int>(target_source_rect.left);
+  output_region.y = static_cast<int>(target_source_rect.top);
+  output_region.width =
+      static_cast<int>(target_source_rect.right - target_source_rect.left);
+  output_region.height =
+      static_cast<int>(target_source_rect.bottom - target_source_rect.top);
   param.output_region = &output_region;
 
-  DUMPTRACE("surface_region: (%d, %d, %d, %d)\n",
-             surface_region.x, surface_region.y,
-             surface_region.width, surface_region.height);
-  DUMPTRACE("Layer DisplayFrame:(%d,%d,%d,%d)\n",
-             display_frame.left, display_frame.top,
-             display_frame.right, display_frame.bottom);
+  DUMPTRACE("surface_region: (%d, %d, %d, %d)\n", surface_region.x,
+            surface_region.y, surface_region.width, surface_region.height);
+  DUMPTRACE("Layer DisplayFrame:(%d,%d,%d,%d)\n", output_region.x,
+            output_region.y, output_region.width, output_region.height);
 
   param.surface = surface_in;
   param.surface_color_standard = VAProcColorStandardBT601;
index 345c819..587a496 100644 (file)
@@ -82,6 +82,9 @@ void OverlayLayer::SetBuffer(HWCNativeHandle handle, int32_t acquire_fence,
     }
   }
   imported_buffer_.reset(new ImportedBuffer(buffer, acquire_fence));
+  if (!register_buffer) {
+    ValidateForOverlayUsage();
+  }
 }
 
 void OverlayLayer::SetBlending(HWCBlending blending) {
index 78b2ec5..0608659 100644 (file)
@@ -154,6 +154,14 @@ struct OverlayLayer {
     return gpu_rendered_;
   }
 
+  bool IsUsingPlaneScalar() const {
+    return display_Scaled_;
+  }
+
+  void UsePlaneScalar() {
+    display_Scaled_ = true;
+  }
+
   // Returns true if we should prefer
   // a separate plane for this layer
   // when validating layers in
@@ -232,6 +240,7 @@ struct OverlayLayer {
       kLayerAttributesChanged | kLayerContentChanged | kDimensionsChanged;
   std::unique_ptr<ImportedBuffer> imported_buffer_;
   bool gpu_rendered_ = false;
+  bool display_Scaled_ = false;
   HWCLayerType type_ = kLayerNormal;
 };
 
index fa652f4..3f360e7 100644 (file)
@@ -112,13 +112,17 @@ bool DisplayPlaneManager::ValidateLayers(
       return render_layers;
     } else {
       DisplayPlaneState &last_plane = composition.back();
-      if (primary_layer->IsVideoLayer())
+      if (primary_layer->IsVideoLayer()) {
         last_plane.SetVideoPlane();
+      }
 
       ResetPlaneTarget(last_plane, commit_planes.back());
     }
   }
 
+  if (render_layers)
+    ValidateForDisplayScaling(composition, commit_planes, primary_layer);
+
   // We are just compositing Primary layer and nothing else.
   if (layers.size() == 1) {
     return render_layers;
@@ -129,11 +133,18 @@ bool DisplayPlaneManager::ValidateLayers(
     uint32_t index = 0;
     for (auto j = overlay_planes_.begin() + 1; j != overlay_planes_.end();
          ++j) {
-      DisplayPlaneState &last_plane = composition.back();
 #ifdef DISABLE_CURSOR_PLANE
       if (cursor_plane_ == j->get())
         continue;
 #endif
+      DisplayPlaneState &last_plane = composition.back();
+      OverlayLayer *previous_layer = NULL;
+      if (previous_layer &&
+          last_plane.GetCompositionState() ==
+              DisplayPlaneState::State::kRender) {
+        ValidateForDisplayScaling(composition, commit_planes, previous_layer);
+        render_layers = true;
+      }
 
       // Handle remaining overlay planes.
       for (auto i = layer_begin; i != layer_end; ++i) {
@@ -163,22 +174,25 @@ bool DisplayPlaneManager::ValidateLayers(
             }
 
             ResetPlaneTarget(last_plane, commit_planes.back());
-            render_layers = true;
           }
 
           prefer_seperate_plane = layer->PreferSeparatePlane();
           break;
         } else {
           last_plane.AddLayer(i->GetZorder(), i->GetDisplayFrame(), false);
+          if (!last_plane.GetOffScreenTarget()) {
+            SetOffScreenPlaneTarget(last_plane);
+          }
+
           commit_planes.pop_back();
         }
-      }
 
-      if (last_plane.GetCompositionState() == DisplayPlaneState::State::kRender)
-        render_layers = true;
+        previous_layer = layer;
+      }
     }
 
     DisplayPlaneState &last_plane = composition.back();
+    OverlayLayer *previous_layer = NULL;
     // We dont have any additional planes. Pre composite remaining layers
     // to the last overlay plane.
     for (auto i = layer_begin; i != layer_end; ++i) {
@@ -187,10 +201,20 @@ bool DisplayPlaneManager::ValidateLayers(
       }
 
       last_plane.AddLayer(i->GetZorder(), i->GetDisplayFrame(), false);
+      previous_layer = &(*(i));
     }
 
-    if (last_plane.GetCompositionState() == DisplayPlaneState::State::kRender)
+    if (last_plane.GetCompositionState() == DisplayPlaneState::State::kRender) {
+      if (previous_layer) {
+        if (!last_plane.GetOffScreenTarget()) {
+          EnsureOffScreenTarget(last_plane);
+        }
+
+        ValidateForDisplayScaling(composition, commit_planes, previous_layer);
+      }
+
       render_layers = true;
+    }
   }
 
   bool render_cursor_layer = ValidateCursorLayer(cursor_layers, composition);
@@ -204,10 +228,13 @@ bool DisplayPlaneManager::ValidateLayers(
       if (plane.GetCompositionState() == DisplayPlaneState::State::kRender) {
         const std::vector<size_t> &source_layers = plane.source_layers();
         size_t layers_size = source_layers.size();
+        bool useplanescalar = plane.IsUsingPlaneScalar();
         for (size_t i = 0; i < layers_size; i++) {
           size_t source_index = source_layers.at(i);
           OverlayLayer &layer = layers.at(source_index);
           layer.GPURendered();
+          if (useplanescalar)
+            layer.UsePlaneScalar();
         }
       }
     }
@@ -326,6 +353,99 @@ bool DisplayPlaneManager::ValidateCursorLayer(
   return status;
 }
 
+void DisplayPlaneManager::ValidateForDisplayScaling(
+    DisplayPlaneStateList &composition,
+    std::vector<OverlayPlane> &commit_planes, OverlayLayer *current_layer) {
+  DisplayPlaneState &last_plane = composition.back();
+  last_plane.UsePlaneScalar(false);
+  last_plane.GetOffScreenTarget()->GetLayer()->SetSourceCrop(
+      last_plane.GetDisplayFrame());
+  last_plane.SetSourceCrop(HwcRect<float>(last_plane.GetDisplayFrame()));
+
+  // TODO: Handle case where all layers to be compoisted have same scaling
+  // ratio.
+  // We cannot use plane scaling for Layers with different scaling ratio.
+  if (last_plane.source_layers().size() > 1) {
+    return;
+  }
+
+  uint32_t display_frame_width = current_layer->GetDisplayFrameWidth();
+  uint32_t display_frame_height = current_layer->GetDisplayFrameHeight();
+  uint32_t source_crop_width = current_layer->GetSourceCropWidth();
+  uint32_t source_crop_height = current_layer->GetSourceCropHeight();
+  // Source and Display frame width, height are same and scaling is not needed.
+  if ((display_frame_width == source_crop_width) &&
+      (display_frame_height == source_crop_height)) {
+    return;
+  }
+
+  // Display frame width, height is lesser than Source. Let's downscale
+  // it with our compositor backend.
+  if ((display_frame_width < source_crop_width) &&
+      (display_frame_height < source_crop_height)) {
+    return;
+  }
+
+  // Display frame height is less. If the cost of upscaling width is less
+  // than downscaling height, than return.
+  if ((display_frame_width > source_crop_width) &&
+      (display_frame_height < source_crop_height)) {
+    uint32_t width_cost =
+        (display_frame_width - source_crop_width) * display_frame_height;
+    uint32_t height_cost =
+        (source_crop_height - display_frame_height) * display_frame_width;
+    if (height_cost > width_cost) {
+      return;
+    }
+  }
+
+  // Display frame width is less. If the cost of upscaling height is less
+  // than downscaling width, than return.
+  if ((display_frame_width < source_crop_width) &&
+      (display_frame_height > source_crop_height)) {
+    uint32_t width_cost =
+        (source_crop_width - display_frame_width) * display_frame_height;
+    uint32_t height_cost =
+        (display_frame_height - source_crop_height) * display_frame_width;
+    if (width_cost > height_cost) {
+      return;
+    }
+  }
+
+  // Case where we are not rotating the layer and format is supported by the
+  // plane.
+  // If we are here this means the layer cannot be scaled using display, just
+  // return.
+  if ((current_layer->GetPlaneTransform() == HWCTransform::kIdentity) &&
+      last_plane.plane()->IsSupportedFormat(
+          current_layer->GetBuffer()->GetFormat())) {
+    return;
+  }
+
+  // TODO: Scalars are limited in HW. Determine scaling ratio
+  // which would really benefit vs doing it in GPU side.
+
+  // Display frame and Source rect are different, let's check if
+  // we can take advantage of scalars attached to this plane.
+  last_plane.SetSourceCrop(current_layer->GetSourceCrop());
+  last_plane.GetOffScreenTarget()->GetLayer()->SetSourceCrop(
+      current_layer->GetSourceCrop());
+
+  OverlayPlane &last_overlay_plane = commit_planes.back();
+  last_overlay_plane.layer = last_plane.GetOverlayLayer();
+
+  bool fall_back =
+      FallbacktoGPU(last_plane.plane(),
+                    last_plane.GetOffScreenTarget()->GetLayer(), commit_planes);
+  if (fall_back) {
+    last_plane.GetOffScreenTarget()->GetLayer()->SetSourceCrop(
+        last_plane.GetDisplayFrame());
+    last_plane.SetSourceCrop(HwcRect<float>(last_plane.GetDisplayFrame()));
+  } else {
+    last_plane.UsePlaneScalar(true);
+  }
+}
+
 void DisplayPlaneManager::ResetPlaneTarget(DisplayPlaneState &plane,
                                            OverlayPlane &overlay_plane) {
   SetOffScreenPlaneTarget(plane);
@@ -486,7 +606,6 @@ bool DisplayPlaneManager::FallbacktoGPU(
 
   // TODO(kalyank): Take relevant factors into consideration to determine if
   // Plane Composition makes sense. i.e. layer size etc
-
   if (!plane_handler_->TestCommit(commit_planes)) {
     return true;
   }
@@ -494,6 +613,21 @@ bool DisplayPlaneManager::FallbacktoGPU(
   return false;
 }
 
+bool DisplayPlaneManager::PreferDisplayScaling(DisplayPlane *target_plane,
+                                               OverlayLayer *layer) const {
+  if ((layer->GetDisplayFrameWidth() == layer->GetSourceCropWidth()) &&
+      (layer->GetDisplayFrameHeight() == layer->GetSourceCropHeight())) {
+    return false;
+  }
+
+  if ((layer->GetPlaneTransform() == HWCTransform::kIdentity) &&
+      target_plane->IsSupportedFormat(layer->GetBuffer()->GetFormat())) {
+    return false;
+  }
+
+  return true;
+}
+
 bool DisplayPlaneManager::CheckPlaneFormat(uint32_t format) {
   return primary_plane_->IsSupportedFormat(format);
 }
index 5ea4e2c..7fb18ff 100644 (file)
@@ -91,6 +91,13 @@ class DisplayPlaneManager {
 
   void PreparePlaneForCursor(DisplayPlaneState *plane);
 
+  bool PreferDisplayScaling(DisplayPlane *target_plane,
+                            OverlayLayer *layer) const;
+
+  void ValidateForDisplayScaling(DisplayPlaneStateList &composition,
+                                 std::vector<OverlayPlane> &commit_planes,
+                                 OverlayLayer *current_layer);
+
   DisplayPlaneHandler *plane_handler_;
   ResourceManager *resource_manager_;
   DisplayPlane *cursor_plane_;
index ca01020..d74b188 100644 (file)
@@ -61,6 +61,14 @@ class DisplayPlaneState {
     return display_frame_;
   }
 
+  const HwcRect<float> &GetSourceCrop() const {
+    return source_crop_;
+  }
+
+  void SetSourceCrop(const HwcRect<float> &crop) {
+    source_crop_ = crop;
+  }
+
   void AddLayer(size_t index, const HwcRect<int> &display_frame,
                 bool cursor_layer) {
     display_frame_.left = std::min(display_frame_.left, display_frame.left);
@@ -164,7 +172,6 @@ class DisplayPlaneState {
 
   void SetOverlayLayer(const OverlayLayer *layer) {
     layer_ = layer;
-    display_frame_ = layer->GetDisplayFrame();
   }
 
   void ReUseOffScreenTarget() {
@@ -279,6 +286,14 @@ class DisplayPlaneState {
     type_ = PlaneType::kVideo;
   }
 
+  void UsePlaneScalar(bool enable) {
+    use_plane_scalar_ = enable;
+  }
+
+  bool IsUsingPlaneScalar() const {
+    return use_plane_scalar_;
+  }
+
  private:
   enum class PlaneType : int32_t {
     kCursor,  // Plane is compositing only Cursor.
@@ -289,11 +304,13 @@ class DisplayPlaneState {
   DisplayPlane *plane_ = NULL;
   const OverlayLayer *layer_ = NULL;
   HwcRect<int> display_frame_;
+  HwcRect<float> source_crop_;
   std::vector<size_t> source_layers_;
   std::vector<CompositionRegion> composition_region_;
   bool recycled_surface_ = false;
   bool has_cursor_layer_ = false;
   bool surface_swapped_ = true;
+  bool use_plane_scalar_ = false;
   std::vector<NativeSurface *> surfaces_;
   PlaneType type_ = PlaneType::kNormal;
 };
index ffe89b1..d530470 100644 (file)
@@ -164,6 +164,7 @@ void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
 
     if (plane.IsVideoPlane()) {
       last_plane.SetVideoPlane();
+      last_plane.SetSourceCrop(plane.GetSourceCrop());
     }
 
     if (plane_state_render || plane.SurfaceRecycled()) {