sde: Choose appropriate rotator output format.

Select the optimal rotator output format for the input layer that
requires rotation/rotator for downscaling.

Change-Id: If10430d189b388b86a94165a5c82257e22bde516
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index 96ec20f..d85fd98 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -44,8 +44,6 @@
   @sa Layer
 */
 enum LayerBlending {
-  kBlendingNone,            //!< Blend operation is not specified.
-
   kBlendingOpaque,          //!< Pixel color is expressed using straight alpha in color tuples. It
                             //!< is constant blend operation. The layer would appear opaque if plane
                             //!< alpha is 0xFF.
@@ -203,7 +201,7 @@
 
   uint32_t frame_rate;              //!< Rate at which frames are being updated for this layer.
 
-  Layer() : input_buffer(NULL), composition(kCompositionGPU), blending(kBlendingNone),
+  Layer() : input_buffer(NULL), composition(kCompositionGPU), blending(kBlendingOpaque),
             plane_alpha(0), frame_rate(0) { }
 };
 
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index c6c2a0a..49abafe 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -69,6 +69,7 @@
   uint32_t max_sde_clk;
   float clk_fudge_factor;
   bool has_bwc;
+  bool has_ubwc;
   bool has_decimation;
   bool has_macrotile;
   bool has_rotator_downscale;
@@ -80,7 +81,7 @@
       num_cursor_pipe(0), num_blending_stages(0), num_rotator(0), num_control(0),
       num_mixer_to_disp(0), smp_total(0), smp_size(0), num_smp_per_pipe(0), max_scale_up(1),
       max_scale_down(1), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
-      max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
+      max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false), has_ubwc(false),
       has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
       has_non_scalar_rgb(false), is_src_split(false) { }
 
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index ea90dfb..4624a35 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -42,13 +42,13 @@
   }
 }
 
-void ResManager::RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
-                                const float &downscale, LayerRect *src_rect,
+void ResManager::RotationConfig(const Layer &layer, const float &downscale, LayerRect *src_rect,
                                 struct HWLayerConfig *layer_config, uint32_t *rotate_count) {
   HWRotateInfo *rotate = &layer_config->rotates[0];
   float src_width = src_rect->right - src_rect->left;
   float src_height = src_rect->bottom - src_rect->top;
-  bool rot90 = IsRotationNeeded(transform.rotation);
+  bool rot90 = IsRotationNeeded(layer.transform.rotation);
+  bool is_opaque = (layer.blending == kBlendingOpaque);
   LayerRect dst_rect;
   // Rotate output is a temp buffer, always output to the top left corner for saving memory
   dst_rect.top = 0.0f;
@@ -56,7 +56,7 @@
 
   rotate->downscale_ratio = downscale;
   uint32_t align_x, align_y;
-  GetAlignFactor(format, &align_x, &align_y);
+  GetAlignFactor(layer.input_buffer->format, &align_x, &align_y);
 
   // downscale when doing rotation
   if (rot90) {
@@ -84,10 +84,11 @@
   rotate->dst_roi = dst_rect;
 
   // Set WHF for Rotator output
-  LayerBufferFormat ouput_format;
-  SetRotatorOutputFormat(format, false /* bwc */, rot90, downscale, &ouput_format);
+  LayerBufferFormat output_format;
+  SetRotatorOutputFormat(layer.input_buffer->format, is_opaque, rot90, (downscale > 1.0f),
+                         &output_format);
   HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
-  hw_buffer_info->buffer_config.format = ouput_format;
+  hw_buffer_info->buffer_config.format = output_format;
   hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right);
   hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom);
 
@@ -279,8 +280,7 @@
 
     LayerTransform transform = layer.transform;
     if (IsRotationNeeded(transform.rotation) || UINT32(rot_scale) != 1) {
-      RotationConfig(layer.input_buffer->format, layer.transform, rot_scale, &src_rect,
-                     layer_config, rotate_count);
+      RotationConfig(layer, rot_scale, &src_rect, layer_config, rotate_count);
       // rotator will take care of flipping, reset tranform
       transform = LayerTransform();
     }
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 09b64ab..c6f9f64 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -1113,38 +1113,76 @@
   }
 }
 
-void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
-                                        bool downscale, LayerBufferFormat *output_format) {
+void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format,
+                                        const bool &is_opaque, const bool &rot90,
+                                        const bool &downscale, LayerBufferFormat *output_format) {
+  // Initialize the output format with input format by default.
   *output_format = input_format;
 
-  switch (input_format) {
-  case kFormatRGB565:
-    if (rot90)
-      *output_format = kFormatRGB888;
-    break;
+  switch(input_format) {
+  case kFormatARGB8888:
   case kFormatRGBA8888:
-    if (bwc)
-      *output_format = kFormatBGRA8888;
+    if (is_opaque) {
+      *output_format = kFormatRGB888;
+    }
     break;
-  case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatBGRA8888:
+    if (is_opaque) {
+      *output_format = kFormatBGR888;
+    }
+    break;
+  case kFormatBGRX8888:
+    *output_format = kFormatBGR888;
+    break;
+  case kFormatXRGB8888:
+  case kFormatRGBX8888:
+    *output_format = kFormatRGB888;
+    break;
   case kFormatYCbCr420SemiPlanar:
-    if (rot90)
-      *output_format = kFormatYCrCb420SemiPlanar;
-    break;
-  case kFormatYCbCr420SPVenusUbwc:
-    if (downscale)
-      *output_format = kFormatYCrCb420SemiPlanar;
-    break;
-  case kFormatYCbCr420Planar:
-  case kFormatYCrCb420Planar:
-    *output_format = kFormatYCrCb420SemiPlanar;
+  case kFormatYCbCr420SemiPlanarVenus:
+    *output_format = kFormatYCbCr420SemiPlanar;
     break;
   default:
+    *output_format = input_format;
     break;
   }
 
-  DLOGV_IF(kTagResources, "Input format %x, Output format = %x, rot90 %d", input_format,
-           *output_format, rot90);
+  // TODO(user): UBWC RGB formats will be handled separately
+  if (downscale) {
+    switch (input_format) {
+    case kFormatYCbCr420SPVenusUbwc:
+      *output_format = kFormatYCbCr420SemiPlanar;
+      break;
+    default:
+      break;
+    }
+  } else {
+    if (hw_res_info_.has_ubwc) {
+      switch (input_format) {
+      case kFormatYCbCr420SemiPlanar:
+      case kFormatYCbCr420SemiPlanarVenus:
+        *output_format = kFormatYCbCr420SPVenusUbwc;
+        break;
+      default:
+        break;
+      }
+    }
+  }
+
+  if (rot90) {
+    if (input_format == kFormatYCbCr422H2V1SemiPlanar) {
+      *output_format = kFormatYCbCr422H1V2SemiPlanar;
+    } else if (input_format == kFormatYCbCr422H1V2SemiPlanar) {
+      *output_format = kFormatYCbCr422H2V1SemiPlanar;
+    } else if (input_format == kFormatYCrCb422H2V1SemiPlanar) {
+      *output_format = kFormatYCrCb422H1V2SemiPlanar;
+    } else if (input_format == kFormatYCrCb422H1V2SemiPlanar) {
+      *output_format = kFormatYCrCb422H2V1SemiPlanar;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "Input format %x, Output format = %x, rot90 %d ubwc %d downscale %d",
+           input_format, *output_format, rot90, hw_res_info_.has_ubwc, downscale);
 
   return;
 }
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 7f78b29..c293453 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -196,16 +196,16 @@
   bool IsMacroTileFormat(const LayerBuffer *buffer) { return buffer->flags.macro_tile; }
   bool IsRotationNeeded(float rotation)
          { return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
-  void RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
-                      const float &downscale, LayerRect *src_rect,
-                      struct HWLayerConfig *layer_config, uint32_t *rotate_count);
+  void RotationConfig(const Layer &layer, const float &downscale, LayerRect *src_rect,
+                      HWLayerConfig *layer_config, uint32_t *rotate_count);
   DisplayError AcquireRotator(DisplayResourceContext *display_resource_ctx,
                               const uint32_t roate_cnt);
   void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
   void ClearRotator(DisplayResourceContext *display_resource_ctx);
   DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
-  void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
-                              bool downscale, LayerBufferFormat *output_format);
+  void SetRotatorOutputFormat(const LayerBufferFormat &input_format, const bool &is_opaque,
+                              const bool &rot90, const bool &downscale,
+                              LayerBufferFormat *output_format);
   DisplayError AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
                                HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
                                uint32_t align_x, uint32_t align_y);
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index e2327c5..cd21c8a 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -596,7 +596,7 @@
   switch (source) {
   case HWC_BLENDING_PREMULT:    *target = kBlendingPremultiplied;   break;
   case HWC_BLENDING_COVERAGE:   *target = kBlendingCoverage;        break;
-  default:                      *target = kBlendingNone;            break;
+  default:                      *target = kBlendingOpaque;          break;
   }
 }