Snap for 6290619 from dedb1edb343f7c3ca032f179d3020bb01c0dc070 to sdk-release

Change-Id: I955555089ba828462f71ae974a8689bee02f5693
diff --git a/compositor/drmdisplaycompositor.cpp b/compositor/drmdisplaycompositor.cpp
index e6f6922..1519736 100644
--- a/compositor/drmdisplaycompositor.cpp
+++ b/compositor/drmdisplaycompositor.cpp
@@ -23,6 +23,7 @@
 #include <sched.h>
 #include <stdlib.h>
 #include <time.h>
+#include <array>
 #include <sstream>
 #include <vector>
 
@@ -40,6 +41,15 @@
 
 namespace android {
 
+std::ostream &operator<<(std::ostream &str, FlatteningState state) {
+  std::array<const char *, 6> flattenting_state_str = {
+      "None",   "Not needed", "SF Requested", "Squashed by GPU",
+      "Serial", "Concurrent",
+  };
+
+  return str << flattenting_state_str[static_cast<int>(state)];
+}
+
 class CompositorVsyncCallback : public VsyncCallback {
  public:
   CompositorVsyncCallback(DrmDisplayCompositor *compositor)
@@ -63,7 +73,9 @@
       dump_frames_composited_(0),
       dump_last_timestamp_ns_(0),
       flatten_countdown_(FLATTEN_COUNTDOWN_INIT),
-      writeback_fence_(-1) {
+      writeback_fence_(-1),
+      flattening_state_(FlatteningState::kNone),
+      frames_flattened_(0) {
   struct timespec ts;
   if (clock_gettime(CLOCK_MONOTONIC, &ts))
     return;
@@ -143,6 +155,19 @@
   return comp;
 }
 
+FlatteningState DrmDisplayCompositor::GetFlatteningState() const {
+  return flattening_state_;
+}
+
+uint32_t DrmDisplayCompositor::GetFlattenedFramesCount() const {
+  return frames_flattened_;
+}
+
+bool DrmDisplayCompositor::ShouldFlattenOnClient() const {
+  return flattening_state_ == FlatteningState::kClientRequested ||
+         flattening_state_ == FlatteningState::kClientDone;
+}
+
 std::tuple<uint32_t, uint32_t, int>
 DrmDisplayCompositor::GetActiveModeResolution() {
   DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
@@ -605,6 +630,11 @@
   active_composition_.swap(composition);
 
   flatten_countdown_ = FLATTEN_COUNTDOWN_INIT;
+  if (flattening_state_ != FlatteningState::kClientRequested) {
+    SetFlattening(FlatteningState::kNone);
+  } else {
+    SetFlattening(FlatteningState::kClientDone);
+  }
   vsync_worker_.VSyncControl(!writeback);
 }
 
@@ -761,6 +791,52 @@
   return 0;
 }
 
+void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) {
+  if (flattening_state_ != new_state) {
+    switch (flattening_state_) {
+      case FlatteningState::kClientDone:
+      case FlatteningState::kConcurrent:
+      case FlatteningState::kSerial:
+        ++frames_flattened_;
+        break;
+      case FlatteningState::kClientRequested:
+      case FlatteningState::kNone:
+      case FlatteningState::kNotNeeded:
+        break;
+    }
+  }
+  flattening_state_ = new_state;
+}
+
+bool DrmDisplayCompositor::IsFlatteningNeeded() const {
+  return CountdownExpired() && active_composition_->layers().size() >= 2;
+}
+
+int DrmDisplayCompositor::FlattenOnClient() {
+  if (refresh_display_cb_) {
+    {
+      AutoLock lock(&lock_, __func__);
+      if (!IsFlatteningNeeded()) {
+        if (flattening_state_ != FlatteningState::kClientDone) {
+          ALOGV("Flattening is not needed");
+          SetFlattening(FlatteningState::kNotNeeded);
+        }
+        return -EALREADY;
+      }
+    }
+
+    ALOGV(
+        "No writeback connector available, "
+        "falling back to client composition");
+    SetFlattening(FlatteningState::kClientRequested);
+    refresh_display_cb_(display_);
+    return 0;
+  } else {
+    ALOGV("No writeback connector available");
+    return -EINVAL;
+  }
+}
+
 // Flatten a scene by enabling the writeback connector attached
 // to the same CRTC as the one driving the display.
 int DrmDisplayCompositor::FlattenSerial(DrmConnector *writeback_conn) {
@@ -776,8 +852,9 @@
   int ret = lock.Lock();
   if (ret)
     return ret;
-  if (!CountdownExpired() || active_composition_->layers().size() < 2) {
+  if (!IsFlatteningNeeded()) {
     ALOGV("Flattening is not needed");
+    SetFlattening(FlatteningState::kNotNeeded);
     return -EALREADY;
   }
 
@@ -884,8 +961,9 @@
   ret = lock.Lock();
   if (ret)
     return ret;
-  if (!CountdownExpired() || active_composition_->layers().size() < 2) {
+  if (!IsFlatteningNeeded()) {
     ALOGV("Flattening is not needed");
+    SetFlattening(FlatteningState::kNotNeeded);
     return -EALREADY;
   }
   DrmCrtc *crtc = active_composition_->crtc();
@@ -955,13 +1033,16 @@
   DrmConnector *writeback_conn = resource_manager_->AvailableWritebackConnector(
       display_);
   if (!active_composition_ || !writeback_conn) {
-    ALOGV("No writeback connector available");
-    return -EINVAL;
+    // Try to fallback to GPU composition on client, since it is more
+    // power-efficient than composition on device side
+    return FlattenOnClient();
   }
 
   if (writeback_conn->display() != display_) {
+    SetFlattening(FlatteningState::kConcurrent);
     return FlattenConcurrent(writeback_conn);
   } else {
+    SetFlattening(FlatteningState::kSerial);
     return FlattenSerial(writeback_conn);
   }
 
diff --git a/drm/drmconnector.cpp b/drm/drmconnector.cpp
index 7cde7cd..81c2b98 100644
--- a/drm/drmconnector.cpp
+++ b/drm/drmconnector.cpp
@@ -58,6 +58,10 @@
     ALOGE("Could not get CRTC_ID property\n");
     return ret;
   }
+  ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_);
+  if (ret) {
+    ALOGW("Could not get EDID property\n");
+  }
   if (writeback()) {
     ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS",
                                      &writeback_pixel_formats_);
@@ -191,6 +195,10 @@
   return crtc_id_property_;
 }
 
+const DrmProperty &DrmConnector::edid_property() const {
+  return edid_property_;
+}
+
 const DrmProperty &DrmConnector::writeback_pixel_formats() const {
   return writeback_pixel_formats_;
 }
diff --git a/drm/drmdevice.cpp b/drm/drmdevice.cpp
index bcb9ddd..bef41d8 100644
--- a/drm/drmdevice.cpp
+++ b/drm/drmdevice.cpp
@@ -126,7 +126,7 @@
   /* TODO: Use drmOpenControl here instead */
   fd_.Set(open(path, O_RDWR));
   if (fd() < 0) {
-    ALOGE("Failed to open dri- %s", strerror(-errno));
+    ALOGE("Failed to open dri %s: %s", path, strerror(errno));
     return std::make_tuple(-ENODEV, 0);
   }
 
diff --git a/drm/drmeventlistener.cpp b/drm/drmeventlistener.cpp
index 8f655a7..ccee0d6 100644
--- a/drm/drmeventlistener.cpp
+++ b/drm/drmeventlistener.cpp
@@ -38,7 +38,7 @@
 int DrmEventListener::Init() {
   uevent_fd_.Set(socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT));
   if (uevent_fd_.get() < 0) {
-    ALOGE("Failed to open uevent socket %d", uevent_fd_.get());
+    ALOGE("Failed to open uevent socket: %s", strerror(errno));
     return uevent_fd_.get();
   }
 
@@ -50,7 +50,7 @@
 
   int ret = bind(uevent_fd_.get(), (struct sockaddr *)&addr, sizeof(addr));
   if (ret) {
-    ALOGE("Failed to bind uevent socket %d", -errno);
+    ALOGE("Failed to bind uevent socket: %s", strerror(errno));
     return -errno;
   }
 
diff --git a/drm/resourcemanager.cpp b/drm/resourcemanager.cpp
index 6e23561..da1a2db 100644
--- a/drm/resourcemanager.cpp
+++ b/drm/resourcemanager.cpp
@@ -50,6 +50,10 @@
     return ret ? -EINVAL : ret;
   }
 
+  char scale_with_gpu[PROPERTY_VALUE_MAX];
+  property_get("hwc.drm.scale_with_gpu", scale_with_gpu, "0");
+  scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1));
+
   return hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
                        (const hw_module_t **)&gralloc_);
 }
diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp
index ab39144..605406b 100644
--- a/drmhwctwo.cpp
+++ b/drmhwctwo.cpp
@@ -142,6 +142,7 @@
           << ((delta.failed_kms_present_ > 0)
                   ? " !!! Internal failure, FIX it please\n"
                   : "")
+          << " Flattened frames: " << delta.frames_flattened_ << "\n"
           << " Pixel operations (free units)"
           << " : [TOTAL: " << delta.total_pixops_
           << " / GPU: " << delta.gpu_pixops_ << "]\n"
@@ -152,6 +153,8 @@
 std::string DrmHwcTwo::HwcDisplay::Dump() {
   auto out = (std::stringstream()
               << "- Display on: " << connector_->name() << "\n"
+              << "  Flattening state: " << compositor_.GetFlatteningState()
+              << "\n"
               << "Statistics since system boot:\n"
               << DumpDelta(total_stats_) << "\n\n"
               << "Statistics since last dumpsys request:\n"
@@ -208,6 +211,12 @@
         HandleInitialHotplugState(device.get());
       break;
     }
+    case HWC2::Callback::Refresh: {
+      for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
+           displays_)
+        d.second.RegisterRefreshCallback(data, function);
+      break;
+    }
     case HWC2::Callback::Vsync: {
       for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
            displays_)
@@ -310,6 +319,15 @@
   return HWC2::Error::None;
 }
 
+void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback(
+    hwc2_callback_data_t data, hwc2_function_pointer_t func) {
+  supported(__func__);
+  auto hook = reinterpret_cast<HWC2_PFN_REFRESH>(func);
+  compositor_.SetRefreshCallback([data, hook](int display) {
+    hook(data, static_cast<hwc2_display_t>(display));
+  });
+}
+
 HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() {
   supported(__func__);
   for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
@@ -900,59 +918,107 @@
 
   int client_start = -1, client_size = 0;
 
-  for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
-    if (!HardwareSupportsLayerType(l.second->sf_type()) ||
-        !importer_->CanImportBuffer(l.second->buffer()) ||
-        color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY) {
-      if (client_start < 0)
-        client_start = l.first;
-      client_size = (l.first - client_start) + 1;
-    }
-  }
-
-  int extra_client = (z_map.size() - client_size) - avail_planes;
-  if (extra_client > 0) {
-    int start = 0, steps;
-    if (client_size != 0) {
-      int prepend = std::min(client_start, extra_client);
-      int append = std::min(int(z_map.size() - (client_start + client_size)),
-                            extra_client);
-      start = client_start - prepend;
-      client_size += extra_client;
-      steps = 1 + std::min(std::min(append, prepend),
-                           int(z_map.size()) - (start + client_size));
-    } else {
-      client_size = extra_client;
-      steps = 1 + z_map.size() - extra_client;
-    }
-
-    gpu_pixops = INT_MAX;
-    for (int i = 0; i < steps; i++) {
-      uint32_t po = CalcPixOps(z_map, start + i, client_size);
-      if (po < gpu_pixops) {
-        gpu_pixops = po;
-        client_start = start + i;
+  if (compositor_.ShouldFlattenOnClient()) {
+    client_start = 0;
+    client_size = z_map.size();
+    MarkValidated(z_map, client_start, client_size);
+  } else {
+    for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
+      if (!HardwareSupportsLayerType(l.second->sf_type()) ||
+          !importer_->CanImportBuffer(l.second->buffer()) ||
+          color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY ||
+          (l.second->RequireScalingOrPhasing() &&
+           resource_manager_->ForcedScalingWithGpu())) {
+        if (client_start < 0)
+          client_start = l.first;
+        client_size = (l.first - client_start) + 1;
       }
     }
-  }
 
-  MarkValidated(z_map, client_start, client_size);
+    int extra_client = (z_map.size() - client_size) - avail_planes;
+    if (extra_client > 0) {
+      int start = 0, steps;
+      if (client_size != 0) {
+        int prepend = std::min(client_start, extra_client);
+        int append = std::min(int(z_map.size() - (client_start + client_size)),
+                              extra_client);
+        start = client_start - prepend;
+        client_size += extra_client;
+        steps = 1 + std::min(std::min(append, prepend),
+                             int(z_map.size()) - (start + client_size));
+      } else {
+        client_size = extra_client;
+        steps = 1 + z_map.size() - extra_client;
+      }
 
-  if (CreateComposition(true) != HWC2::Error::None) {
-    ++total_stats_.failed_kms_validate_;
-    gpu_pixops = total_pixops;
-    client_size = z_map.size();
-    MarkValidated(z_map, 0, client_size);
+      gpu_pixops = INT_MAX;
+      for (int i = 0; i < steps; i++) {
+        uint32_t po = CalcPixOps(z_map, start + i, client_size);
+        if (po < gpu_pixops) {
+          gpu_pixops = po;
+          client_start = start + i;
+        }
+      }
+    }
+
+    MarkValidated(z_map, client_start, client_size);
+
+    if (CreateComposition(true) != HWC2::Error::None) {
+      ++total_stats_.failed_kms_validate_;
+      gpu_pixops = total_pixops;
+      client_size = z_map.size();
+      MarkValidated(z_map, 0, client_size);
+    }
   }
 
   *num_types = client_size;
 
+  total_stats_.frames_flattened_ = compositor_.GetFlattenedFramesCount();
   total_stats_.gpu_pixops_ += gpu_pixops;
   total_stats_.total_pixops_ += total_pixops;
 
   return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
 }
 
+#if PLATFORM_SDK_VERSION > 28
+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData(
+    uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) {
+  supported(__func__);
+
+  drmModePropertyBlobPtr blob;
+  int ret;
+  uint64_t blob_id;
+
+  std::tie(ret, blob_id) = connector_->edid_property().value();
+  if (ret) {
+    ALOGE("Failed to get edid property value.");
+    return HWC2::Error::Unsupported;
+  }
+
+  blob = drmModeGetPropertyBlob(drm_->fd(), blob_id);
+
+  outData = static_cast<uint8_t *>(blob->data);
+
+  *outPort = connector_->id();
+  *outDataSize = blob->length;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayCapabilities(
+    uint32_t *outNumCapabilities, uint32_t *outCapabilities) {
+  unsupported(__func__, outCapabilities);
+
+  if (outNumCapabilities == NULL) {
+    return HWC2::Error::BadParameter;
+  }
+
+  *outNumCapabilities = 0;
+
+  return HWC2::Error::None;
+}
+#endif /* PLATFORM_SDK_VERSION > 28 */
+
 HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) {
   supported(__func__);
   cursor_x_ = x;
@@ -1275,7 +1341,18 @@
       return ToHook<HWC2_PFN_VALIDATE_DISPLAY>(
           DisplayHook<decltype(&HwcDisplay::ValidateDisplay),
                       &HwcDisplay::ValidateDisplay, uint32_t *, uint32_t *>);
-
+#if PLATFORM_SDK_VERSION > 28
+    case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
+      return ToHook<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
+          DisplayHook<decltype(&HwcDisplay::GetDisplayIdentificationData),
+                      &HwcDisplay::GetDisplayIdentificationData, uint8_t *,
+                      uint32_t *, uint8_t *>);
+    case HWC2::FunctionDescriptor::GetDisplayCapabilities:
+      return ToHook<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
+          DisplayHook<decltype(&HwcDisplay::GetDisplayCapabilities),
+                      &HwcDisplay::GetDisplayCapabilities, uint32_t *,
+                      uint32_t *>);
+#endif /* PLATFORM_SDK_VERSION > 28 */
     // Layer functions
     case HWC2::FunctionDescriptor::SetCursorPosition:
       return ToHook<HWC2_PFN_SET_CURSOR_POSITION>(
diff --git a/include/drmconnector.h b/include/drmconnector.h
index c9fd7ab..dc64b38 100644
--- a/include/drmconnector.h
+++ b/include/drmconnector.h
@@ -62,6 +62,7 @@
 
   const DrmProperty &dpms_property() const;
   const DrmProperty &crtc_id_property() const;
+  const DrmProperty &edid_property() const;
   const DrmProperty &writeback_pixel_formats() const;
   const DrmProperty &writeback_fb_id() const;
   const DrmProperty &writeback_out_fence() const;
@@ -100,6 +101,7 @@
 
   DrmProperty dpms_property_;
   DrmProperty crtc_id_property_;
+  DrmProperty edid_property_;
   DrmProperty writeback_pixel_formats_;
   DrmProperty writeback_fb_id_;
   DrmProperty writeback_out_fence_;
diff --git a/include/drmdisplaycompositor.h b/include/drmdisplaycompositor.h
index 477f226..26e2572 100644
--- a/include/drmdisplaycompositor.h
+++ b/include/drmdisplaycompositor.h
@@ -41,6 +41,17 @@
 
 namespace android {
 
+enum class FlatteningState {
+  kNone,
+  kNotNeeded,
+  kClientRequested,
+  kClientDone,
+  kSerial,
+  kConcurrent
+};
+
+std::ostream &operator<<(std::ostream &str, FlatteningState state);
+
 class DrmDisplayCompositor {
  public:
   DrmDisplayCompositor();
@@ -48,6 +59,11 @@
 
   int Init(ResourceManager *resource_manager, int display);
 
+  template <typename Fn>
+  void SetRefreshCallback(Fn &&refresh_cb) {
+    refresh_display_cb_ = std::forward<Fn>(refresh_cb);
+  }
+
   std::unique_ptr<DrmDisplayComposition> CreateComposition() const;
   std::unique_ptr<DrmDisplayComposition> CreateInitializedComposition() const;
   int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition);
@@ -62,6 +78,10 @@
     return active_composition_->take_out_fence();
   }
 
+  FlatteningState GetFlatteningState() const;
+  uint32_t GetFlattenedFramesCount() const;
+  bool ShouldFlattenOnClient() const;
+
   std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution();
 
  private:
@@ -90,7 +110,11 @@
 
   void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition,
                   int status, bool writeback = false);
+
+  void SetFlattening(FlatteningState new_state);
+  bool IsFlatteningNeeded() const;
   int FlattenActiveComposition();
+  int FlattenOnClient();
   int FlattenSerial(DrmConnector *writeback_conn);
   int FlattenConcurrent(DrmConnector *writeback_conn);
   int FlattenOnDisplay(std::unique_ptr<DrmDisplayComposition> &src,
@@ -126,6 +150,11 @@
   int64_t flatten_countdown_;
   std::unique_ptr<Planner> planner_;
   int writeback_fence_;
+
+  FlatteningState flattening_state_;
+  uint32_t frames_flattened_;
+
+  std::function<void(int)> refresh_display_cb_;
 };
 }  // namespace android
 
diff --git a/include/drmhwctwo.h b/include/drmhwctwo.h
index babe000..2bbe334 100644
--- a/include/drmhwctwo.h
+++ b/include/drmhwctwo.h
@@ -22,6 +22,7 @@
 
 #include <hardware/hwcomposer2.h>
 
+#include <math.h>
 #include <array>
 #include <map>
 
@@ -93,6 +94,19 @@
 
     void PopulateDrmLayer(DrmHwcLayer *layer);
 
+    bool RequireScalingOrPhasing() {
+      float src_width = source_crop_.right - source_crop_.left;
+      float src_height = source_crop_.bottom - source_crop_.top;
+
+      float dest_width = display_frame_.right - display_frame_.left;
+      float dest_height = display_frame_.bottom - display_frame_.top;
+
+      bool scaling = src_width != dest_width || src_height != dest_height;
+      bool phasing = (source_crop_.left - floor(source_crop_.left) != 0) ||
+                     (source_crop_.top - floor(source_crop_.top) != 0);
+      return scaling || phasing;
+    }
+
     // Layer hooks
     HWC2::Error SetCursorPosition(int32_t x, int32_t y);
     HWC2::Error SetLayerBlendMode(int32_t mode);
@@ -149,6 +163,9 @@
 
     HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data,
                                       hwc2_function_pointer_t func);
+    void RegisterRefreshCallback(hwc2_callback_data_t data,
+                                 hwc2_function_pointer_t func);
+
     void ClearDisplay();
 
     std::string Dump();
@@ -173,6 +190,13 @@
                                    uint32_t *num_elements, hwc2_layer_t *layers,
                                    int32_t *layer_requests);
     HWC2::Error GetDisplayType(int32_t *type);
+#if PLATFORM_SDK_VERSION > 28
+    HWC2::Error GetDisplayIdentificationData(uint8_t *outPort,
+                                             uint32_t *outDataSize,
+                                             uint8_t *outData);
+    HWC2::Error GetDisplayCapabilities(uint32_t *outNumCapabilities,
+                                       uint32_t *outCapabilities);
+#endif
     HWC2::Error GetDozeSupport(int32_t *support);
     HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types,
                                    float *max_luminance,
@@ -236,9 +260,11 @@
     struct Stats {
       Stats minus(Stats b) {
         return {total_frames_ - b.total_frames_,
-                total_pixops_ - b.total_pixops_, gpu_pixops_ - b.gpu_pixops_,
+                total_pixops_ - b.total_pixops_,
+                gpu_pixops_ - b.gpu_pixops_,
                 failed_kms_validate_ - b.failed_kms_validate_,
-                failed_kms_present_ - b.failed_kms_present_};
+                failed_kms_present_ - b.failed_kms_present_,
+                frames_flattened_ - b.frames_flattened_};
       }
 
       uint32_t total_frames_ = 0;
@@ -246,6 +272,7 @@
       uint64_t gpu_pixops_ = 0;
       uint32_t failed_kms_validate_ = 0;
       uint32_t failed_kms_present_ = 0;
+      uint32_t frames_flattened_ = 0;
     } total_stats_, prev_stats_;
     std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta);
   };
diff --git a/include/resourcemanager.h b/include/resourcemanager.h
index f10af45..7a86828 100644
--- a/include/resourcemanager.h
+++ b/include/resourcemanager.h
@@ -40,6 +40,9 @@
   int getDisplayCount() const {
     return num_displays_;
   }
+  bool ForcedScalingWithGpu() {
+    return scale_with_gpu_;
+  }
 
  private:
   int AddDrmDevice(std::string path);
@@ -48,6 +51,8 @@
   std::vector<std::unique_ptr<DrmDevice>> drms_;
   std::vector<std::shared_ptr<Importer>> importers_;
   const gralloc_module_t *gralloc_;
+
+  bool scale_with_gpu_;
 };
 }  // namespace android
 
diff --git a/platform/platformimagination.cpp b/platform/platformimagination.cpp
index ea34ecc..bd4a4c3 100644
--- a/platform/platformimagination.cpp
+++ b/platform/platformimagination.cpp
@@ -39,6 +39,8 @@
   bo->usage = hnd->usage;
   bo->prime_fds[0] = hnd->fd[0];
   bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3;
+  bo->hal_format = hnd->iFormat;
+  bo->pixel_stride = hnd->aiStride[0];
 
   switch (hnd->iFormat) {
 #ifdef HAL_PIXEL_FORMAT_BGRX_8888