OSDN Git Service

Added the support of panorama view mode in AaaG HWC.
authorWan Shuang <shuang.wan@intel.com>
Mon, 21 Jan 2019 11:52:55 +0000 (19:52 +0800)
committerLin Johnson <johnson.lin@intel.com>
Tue, 22 Jan 2019 02:28:26 +0000 (10:28 +0800)
This feature support combining 1 physical display and 1 SOS display
like one wide resolution display to AOSP framework. HWC be responsible
to feed the part of screen into physical display and SOS accordingly.

Change-Id: I25bd1b6cf78d8d6b8e6f6c4e73454640e758a3cb
Tracked-On: https://jira.devtools.intel.com/browse/OAM-70254
Tests: AaaG be able to split screen and sharing part of it with SOS.
Signed-off-by: Wan Shuang <shuang.wan@intel.com>
16 files changed:
Android.common.mk
common/Android.mk
common/core/gpudevice.cpp
common/core/mosaicdisplay.cpp
common/core/mosaicdisplay.h
common/display/hyperdmadisplay.h [new file with mode: 0644]
common/display/virtualdisplay.h
common/display/virtualpanoramadisplay.cpp [new file with mode: 0644]
common/display/virtualpanoramadisplay.h [new file with mode: 0644]
hwc_display_virt.ini
public/gpudevice.h
public/hwclayer.h
wsi/Android.mk
wsi/displaymanager.h
wsi/drm/drmdisplaymanager.cpp
wsi/drm/drmdisplaymanager.h

index f51499d..6576fa9 100644 (file)
@@ -47,6 +47,10 @@ $(info "ANDROID_VERSION $(ANDROID_VERSION)")
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
+ifeq ($(strip $(ENABLE_HYPER_DMABUF_SHARING)), true)
+LOCAL_CPPFLAGS += -DENABLE_PANORAMA
+endif
+
 LOCAL_SHARED_LIBRARIES := \
        libcutils \
        libdrm \
index 8bdf2b4..0925c43 100644 (file)
@@ -86,6 +86,11 @@ LOCAL_SRC_FILES := \
         utils/hwcutils.cpp \
         utils/disjoint_layers.cpp
 
+ifeq ($(strip $(ENABLE_HYPER_DMABUF_SHARING)), true)
+LOCAL_CPPFLAGS += -DENABLE_PANORAMA
+LOCAL_SRC_FILES += display/virtualpanoramadisplay.cpp
+endif
+
 ifneq ($(strip $(HWC_DISABLE_VA_DRIVER)), true)
 LOCAL_SHARED_LIBRARIES += \
        libva \
index 4188660..7aa501e 100644 (file)
@@ -172,6 +172,137 @@ void GpuDevice::ParsePlaneReserveSettings(std::string &value) {
   }
 }
 
+#ifdef ENABLE_PANORAMA
+void GpuDevice::ParsePanoramaDisplayConfig(
+    std::string &value, std::vector<std::vector<uint32_t>> &panorama_displays) {
+  std::istringstream i_value(value);
+  std::string i_panorama_split_str;
+  std::vector<uint32_t> panorama_duplicate_check;
+  // Got panorama sub display num
+  std::vector<uint32_t> panorama_display;
+  while (std::getline(i_value, i_panorama_split_str, '+')) {
+    if (i_panorama_split_str.empty() ||
+        i_panorama_split_str.find_first_not_of("0123456789") !=
+            std::string::npos)
+      continue;
+    size_t i_panorama_split_num = atoi(i_panorama_split_str.c_str());
+    // Check and skip if the display already been used in other panorama
+    bool skip_duplicate_display = false;
+    size_t panorama_size = panorama_duplicate_check.size();
+    for (size_t i = 0; i < panorama_size; i++) {
+      if (panorama_duplicate_check.at(i) == i_panorama_split_num) {
+        skip_duplicate_display = true;
+        break;
+      }
+    }
+    if (!skip_duplicate_display) {
+      // save the sub display num for the panorama display (don't care if
+      // the physical/logical display is existing/connected here)
+      panorama_display.emplace_back(i_panorama_split_num);
+      panorama_duplicate_check.emplace_back(i_panorama_split_num);
+    }
+  }
+  panorama_displays.emplace_back(panorama_display);
+}
+
+void GpuDevice::ParsePanoramaSOSDisplayConfig(
+    std::string &value,
+    std::vector<std::vector<uint32_t>> &panorama_sos_displays) {
+  std::istringstream i_value(value);
+  std::string i_panorama_sos_split_str;
+
+  std::vector<uint32_t> panorama_sos_duplicate_check;
+  // Got panorama sub display num
+  std::vector<uint32_t> panorama_sos_display;
+  while (std::getline(i_value, i_panorama_sos_split_str, '+')) {
+    if (i_panorama_sos_split_str.empty() ||
+        i_panorama_sos_split_str.find_first_not_of("0123456789") !=
+            std::string::npos)
+      continue;
+    size_t i_panorama_sos_split_num = atoi(i_panorama_sos_split_str.c_str());
+    // Check and skip if the display already been used in other panorama
+    bool skip_duplicate_display = false;
+    size_t panorama_sos_size = panorama_sos_duplicate_check.size();
+    for (size_t i = 0; i < panorama_sos_size; i++) {
+      if (panorama_sos_duplicate_check.at(i) == i_panorama_sos_split_num) {
+        skip_duplicate_display = true;
+        break;
+      }
+    }
+    if (!skip_duplicate_display) {
+      // save the sub display num for the panorama display (don't care if
+      // the physical/logical display is existing/connected here)
+      panorama_sos_display.emplace_back(i_panorama_sos_split_num);
+      panorama_sos_duplicate_check.emplace_back(i_panorama_sos_split_num);
+    }
+  }
+  panorama_sos_displays.emplace_back(panorama_sos_display);
+}
+
+void GpuDevice::PanoramaInit(
+    std::vector<NativeDisplay *> &total_displays_,
+    std::vector<NativeDisplay *> &temp_displays,
+    std::vector<std::vector<uint32_t>> &panorama_displays,
+    std::vector<std::vector<uint32_t>> &panorama_sos_displays,
+    std::vector<bool> &available_displays) {
+  std::vector<NativeDisplay *> i_available_panorama_displays;
+  temp_displays.swap(total_displays_);
+  // Add the virtual panorama displays mapping the SOS virtual displays.
+  size_t sos_displays_size = panorama_sos_displays.size();
+  for (size_t sos_it = 0; sos_it < sos_displays_size; sos_it++) {
+    NativeDisplay *virtualdisp = display_manager_->CreateVirtualPanoramaDisplay(
+        panorama_sos_displays.at(0).at(sos_it));
+    virtualdisp->InitVirtualDisplay(1920, 1080);
+    i_available_panorama_displays.emplace_back(virtualdisp);
+  }
+
+  // Add the native displays
+  size_t displays_size = temp_displays.size();
+  for (size_t t = 0; t < displays_size; t++) {
+    // Skip the displays which already be marked in other panorama
+    if (!available_displays.at(t)) {
+      ETRACE("display: %u is not present in the vector of avaialble_displays");
+      continue;
+    }
+    bool skip_display = false;
+    size_t panorama_size = panorama_displays.size();
+    for (size_t m = 0; m < panorama_size; m++) {
+      size_t panorama_inner_size = panorama_displays.at(m).size();
+      for (size_t l = 0; l < panorama_inner_size; l++) {
+        // Check if the logical display is in panorama, keep the order of
+        // logical displays list
+        // Get the smallest logical num of the panorama for order keeping
+        if (t == panorama_displays.at(m).at(l)) {
+          if (panorama_displays.at(m).at(l) < displays_size) {
+            // Skip the disconnected display here
+            i_available_panorama_displays.emplace_back(
+                temp_displays.at(panorama_displays.at(m).at(l)));
+            // Add tag for panorama-ed displays
+            available_displays.at(panorama_displays.at(m).at(l)) = false;
+          }
+          skip_display = true;
+          break;
+        }
+      }
+      if (skip_display)
+        break;
+    }
+  }
+  // Create panorama for those logical displays
+  if (i_available_panorama_displays.size() > 0) {
+    std::unique_ptr<MosaicDisplay> panorama(
+        new MosaicDisplay(i_available_panorama_displays));
+    panorama->SetPanoramaMode(true);
+    panorama->SetExtraDispInfo((int)panorama_displays.size(),
+                               (int)panorama_sos_displays.size());
+    panorama_displays_.emplace_back(std::move(panorama));
+    // Save the panorama to the final displays list
+    total_displays_.emplace_back(panorama_displays_.back().get());
+  }
+}
+
+#endif
+
 void GpuDevice::HandleHWCSettings() {
   // Handle config file reading
   const char *hwc_dp_cfg_path = HWC_DISPLAY_INI_PATH;
@@ -189,6 +320,12 @@ void GpuDevice::HandleHWCSettings() {
   std::vector<HwcRect<int32_t>> float_displays;
   std::vector<std::vector<uint32_t>> cloned_displays;
   std::vector<std::vector<uint32_t>> mosaic_displays;
+#ifdef ENABLE_PANORAMA
+  bool use_panorama = false;
+  std::vector<std::vector<uint32_t>> panorama_displays;
+  std::vector<std::vector<uint32_t>> panorama_sos_displays;
+#endif
+
   std::ifstream fin(hwc_dp_cfg_path);
   std::string cfg_line;
   std::string key_logical("LOGICAL");
@@ -203,6 +340,11 @@ void GpuDevice::HandleHWCSettings() {
   std::string key_physical_display_rotation("PHYSICAL_DISPLAY_ROTATION");
   std::string key_clone_display("CLONE_DISPLAY");
   std::string key_float_display("FLOAT_DISPLAY");
+#ifdef ENABLE_PANORAMA
+  std::string key_panorama("PANORAMA");
+  std::string key_panorama_display("PANORAMA_DISPLAY");
+  std::string key_panorama_sos_display("PANORAMA_SOS_DISPLAY");
+#endif
 
   std::string key_reserved_drm_plane("DRM_PLANE_RESERVED");
 
@@ -234,6 +376,13 @@ void GpuDevice::HandleHWCSettings() {
           if (!value.compare(enable_str)) {
             use_mosaic = true;
           }
+#ifdef ENABLE_PANORAMA
+          // Got panorama switch
+        } else if (!key.compare(key_panorama)) {
+          if (!value.compare(enable_str)) {
+            use_panorama = true;
+          }
+#endif
           // Got clone switch
         } else if (!key.compare(key_clone)) {
           if (!value.compare(enable_str)) {
@@ -310,6 +459,16 @@ void GpuDevice::HandleHWCSettings() {
             }
           }
           mosaic_displays.emplace_back(mosaic_display);
+#ifdef ENABLE_PANORAMA
+          // Got panorama config
+        } else if (!key.compare(key_panorama_display)) {
+          ParsePanoramaDisplayConfig(value, panorama_displays);
+          size_t panorama_displays_size = panorama_displays.size();
+          // Got panorama sos config
+        } else if (!key.compare(key_panorama_sos_display)) {
+          ParsePanoramaSOSDisplayConfig(value, panorama_sos_displays);
+          size_t panorama_sos_displays_size = panorama_sos_displays.size();
+#endif
         } else if (!key.compare(key_physical_display)) {
           std::istringstream i_value(value);
           std::string physical_split_str;
@@ -598,7 +757,18 @@ void GpuDevice::HandleHWCSettings() {
     total_displays_.swap(temp_displays);
   }
 
+#ifdef ENABLE_PANORAMA
+  if (use_panorama && !use_mosaic && !use_cloned && !use_float) {
+    PanoramaInit(total_displays_, temp_displays, panorama_displays,
+                 panorama_sos_displays, available_displays);
+  }
+#endif
+
+#ifdef ENABLE_PANORAMA
+  if (use_cloned && !use_mosaic && !use_logical && !use_panorama) {
+#else
   if (use_cloned && !use_mosaic && !use_logical) {
+#endif
     std::vector<NativeDisplay *> temp_displays;
     size_t displays_size = total_displays_.size();
     size_t cloned_displays_size = cloned_displays.size();
@@ -641,10 +811,14 @@ void GpuDevice::HandleHWCSettings() {
     temp_displays.swap(total_displays_);
   }
 
-  // Now set floating display configuration
-  // Get the floating display index and the respective rectangle
-  // TODO Logical display on & mosaic display on scenario
+// Now set floating display configuration
+// Get the floating display index and the respective rectangle
+// TODO Logical display on & mosaic display on scenario
+#ifdef ENABLE_PANORAMA
+  if (use_float && !use_logical && !use_mosaic && !use_panorama) {
+#else
   if (use_float && !use_logical && !use_mosaic) {
+#endif
     bool ret = false;
     size_t size = float_display_indices.size();
     size_t num_displays = total_displays_.size();
index f32794a..8ade9a9 100644 (file)
@@ -349,7 +349,19 @@ void MosaicDisplay::HotPlugUpdate(bool connected) {
   }
 
   vsync_counter_ = total_connected_displays;
+
+#ifdef ENABLE_PANORAMA
+  if (panorama_mode_) {
+    vsync_divisor_ = num_physical_displays_;
+    if (vsync_divisor_ < 1) {
+      vsync_divisor_ = 1;
+    }
+  } else {
+    vsync_divisor_ = vsync_counter_;
+  }
+#else
   vsync_divisor_ = vsync_counter_;
+#endif
 
   if (connected_ == connected) {
     lock_.unlock();
@@ -528,4 +540,16 @@ bool MosaicDisplay::ContainConnector(const uint32_t connector_id) {
   return false;
 }
 
+#ifdef ENABLE_PANORAMA
+void MosaicDisplay::SetPanoramaMode(bool mode) {
+  panorama_mode_ = mode;
+}
+
+void MosaicDisplay::SetExtraDispInfo(int num_physical_displays,
+                                     int num_virtual_displays) {
+  num_physical_displays_ = num_physical_displays;
+  num_virtual_displays_ = num_virtual_displays;
+}
+#endif
+
 }  // namespace hwcomposer
index b1c4716..c078b8e 100644 (file)
@@ -115,6 +115,11 @@ class MosaicDisplay : public NativeDisplay {
 
   bool ContainConnector(const uint32_t connector_id) override;
 
+#ifdef ENABLE_PANORAMA
+  void SetPanoramaMode(bool mode);
+  void SetExtraDispInfo(int num_physical_displays, int num_virtual_displays);
+#endif
+
  private:
   std::vector<NativeDisplay *> physical_displays_;
   std::vector<NativeDisplay *> connected_displays_;
@@ -136,6 +141,11 @@ class MosaicDisplay : public NativeDisplay {
   bool connected_ = false;
   bool pending_vsync_ = false;
   bool update_connected_displays_ = true;
+#ifdef ENABLE_PANORAMA
+  bool panorama_mode_ = false;
+  int32_t num_physical_displays_ = 1;
+  int32_t num_virtual_displays_ = 1;
+#endif
   SpinLock lock_;
 };
 
diff --git a/common/display/hyperdmadisplay.h b/common/display/hyperdmadisplay.h
new file mode 100644 (file)
index 0000000..607e49d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+// Copyright (c) 2016 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef COMMON_DISPLAY_HYPERDMABUF_H_
+#define COMMON_DISPLAY_HYPERDMABUF_H_
+
+#include <memory>
+#include <vector>
+
+#include <linux/hyper_dmabuf.h>
+#include <map>
+#include "drmbuffer.h"
+#include "hwctrace.h"
+#define SURFACE_NAME_LENGTH 64
+#define HYPER_DMABUF_PATH "/dev/hyper_dmabuf"
+
+namespace hwcomposer {
+
+struct vm_header {
+  int32_t version;
+  int32_t output;
+  int32_t counter;
+  int32_t n_buffers;
+  int32_t disp_w;
+  int32_t disp_h;
+};
+
+struct vm_buffer_info {
+  int32_t surf_index;
+  int32_t width, height;
+  int32_t format;
+  int32_t pitch[3];
+  int32_t offset[3];
+  int32_t tile_format;
+  int32_t rotation;
+  int32_t status;
+  int32_t counter;
+  union {
+    hyper_dmabuf_id_t hyper_dmabuf_id;
+    unsigned long ggtt_offset;
+  };
+  char surface_name[SURFACE_NAME_LENGTH];
+  uint64_t surface_id;
+  int32_t bbox[4];
+};
+
+}  // namespace hwcomposer
+#endif  // COMMON_DISPLAY_HYPERDMABUF_H_
index b40bdf3..75e3692 100644 (file)
 #include "compositor.h"
 #include "resourcemanager.h"
 #ifdef HYPER_DMABUF_SHARING
-#include <linux/hyper_dmabuf.h>
-#include <map>
-#include "drmbuffer.h"
-#include "hwctrace.h"
-#define SURFACE_NAME_LENGTH 64
-#define HYPER_DMABUF_PATH "/dev/hyper_dmabuf"
+#include "hyperdmadisplay.h"
 #endif
 
 namespace hwcomposer {
@@ -38,36 +33,6 @@ struct HwcLayer;
 class FrameBufferManager;
 class NativeBufferHandler;
 
-#ifdef HYPER_DMABUF_SHARING
-struct vm_header {
-  int32_t version;
-  int32_t output;
-  int32_t counter;
-  int32_t n_buffers;
-  int32_t disp_w;
-  int32_t disp_h;
-};
-
-struct vm_buffer_info {
-  int32_t surf_index;
-  int32_t width, height;
-  int32_t format;
-  int32_t pitch[3];
-  int32_t offset[3];
-  int32_t tile_format;
-  int32_t rotation;
-  int32_t status;
-  int32_t counter;
-  union {
-    hyper_dmabuf_id_t hyper_dmabuf_id;
-    unsigned long ggtt_offset;
-  };
-  char surface_name[SURFACE_NAME_LENGTH];
-  uint64_t surface_id;
-  int32_t bbox[4];
-};
-#endif
-
 class VirtualDisplay : public NativeDisplay {
  public:
   VirtualDisplay(uint32_t gpu_fd, NativeBufferHandler *buffer_handler,
diff --git a/common/display/virtualpanoramadisplay.cpp b/common/display/virtualpanoramadisplay.cpp
new file mode 100644 (file)
index 0000000..4762a48
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+// Copyright (c) 2016 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "virtualpanoramadisplay.h"
+
+#include <drm_fourcc.h>
+
+#include <hwclayer.h>
+#include <nativebufferhandler.h>
+
+#include <sstream>
+#include <vector>
+
+#include "hwctrace.h"
+#include "overlaylayer.h"
+
+#include "hwcutils.h"
+
+namespace hwcomposer {
+
+VirtualPanoramaDisplay::VirtualPanoramaDisplay(
+    uint32_t gpu_fd, NativeBufferHandler *buffer_handler,
+    FrameBufferManager *frame_buffer_manager, uint32_t pipe_id,
+    uint32_t /*crtc_id*/)
+    : output_handle_(0),
+      acquire_fence_(-1),
+      width_(0),
+      height_(0),
+      display_index_(pipe_id) {
+  resource_manager_.reset(new ResourceManager(buffer_handler));
+  if (!resource_manager_) {
+    ETRACE("Failed to construct hwc layer buffer manager");
+  }
+  fb_manager_ = frame_buffer_manager;
+  compositor_.Init(resource_manager_.get(), gpu_fd, fb_manager_);
+}
+
+void VirtualPanoramaDisplay::InitHyperDmaBuf() {
+  if (hyper_dmabuf_initialized)
+    return;
+#ifdef HYPER_DMABUF_SHARING
+  int ret;
+  struct ioctl_hyper_dmabuf_tx_ch_setup msg;
+  memset(&msg, 0, sizeof(ioctl_hyper_dmabuf_tx_ch_setup));
+
+  mHyperDmaBuf_Fd = open(HYPER_DMABUF_PATH, O_RDWR);
+
+  if (mHyperDmaBuf_Fd < 0)
+    ETRACE("Hyper DmaBuf: open hyper dmabuf device node %s failed because %s",
+           HYPER_DMABUF_PATH, strerror(errno));
+  else {
+    ITRACE("Hyper DmaBuf: open hyper dmabuf device node %s successfully!",
+           HYPER_DMABUF_PATH);
+
+    /* TODO: add config option to specify which domains should be used, for
+     * now we share always with dom0 */
+    msg.remote_domain = 0;
+    ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_TX_CH_SETUP, &msg);
+    if (ret) {
+      ETRACE(
+          "Hyper DmaBuf:"
+          "IOCTL_HYPER_DMABUF_TX_CH_SETUP failed with error %d\n",
+          ret);
+      close(mHyperDmaBuf_Fd);
+      mHyperDmaBuf_Fd = -1;
+    } else
+      ITRACE("Hyper DmaBuf: IOCTL_HYPER_DMABUF_TX_CH_SETUP Done!\n");
+  }
+#endif
+  hyper_dmabuf_initialized = true;
+}
+
+VirtualPanoramaDisplay::~VirtualPanoramaDisplay() {
+  if (acquire_fence_ > 0) {
+    close(acquire_fence_);
+  }
+
+  if (handle_) {
+    ResourceHandle temp;
+    temp.handle_ = handle_;
+    resource_manager_->MarkResourceForDeletion(temp, false);
+  }
+
+  delete output_handle_;
+  std::vector<OverlayLayer>().swap(in_flight_layers_);
+
+  resource_manager_->PurgeBuffer();
+  compositor_.Reset();
+#ifdef HYPER_DMABUF_SHARING
+  if (mHyperDmaBuf_Fd > 0) {
+    auto it = mHyperDmaExportedBuffers.begin();
+    for (; it != mHyperDmaExportedBuffers.end(); ++it) {
+      struct ioctl_hyper_dmabuf_unexport msg;
+      int ret;
+      msg.hid = it->second.hyper_dmabuf_id;
+      // Todo: find a reduced dmabuf free delay time
+      msg.delay_ms = 1000;
+      ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_UNEXPORT, &msg);
+      if (ret) {
+        ETRACE(
+            "Hyper DmaBuf:"
+            "IOCTL_HYPER_DMABUF_UNEXPORT ioctl failed %d [0x%x]\n",
+            ret, it->second.hyper_dmabuf_id.id);
+      } else {
+        ITRACE("Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl Done [0x%x]!\n",
+               it->second.hyper_dmabuf_id.id);
+        mHyperDmaExportedBuffers.erase(it);
+      }
+    }
+
+    close(mHyperDmaBuf_Fd);
+    mHyperDmaBuf_Fd = -1;
+  }
+#endif
+}
+
+void VirtualPanoramaDisplay::InitVirtualDisplay(uint32_t width,
+                                                uint32_t height) {
+  width_ = width;
+  height_ = height;
+  CreateOutBuffer();
+}
+
+bool VirtualPanoramaDisplay::GetActiveConfig(uint32_t *config) {
+  if (!config)
+    return false;
+
+  config[0] = 1;
+  return true;
+}
+
+bool VirtualPanoramaDisplay::SetActiveConfig(uint32_t /*config*/) {
+  return true;
+}
+
+void VirtualPanoramaDisplay::HyperDmaExport() {
+#ifdef HYPER_DMABUF_SHARING
+  int ret = 0;
+  size_t buffer_number = 0;
+  uint32_t surf_index = display_index_;
+  size_t info_size = sizeof(vm_buffer_info);
+  size_t header_size = sizeof(vm_header);
+  vm_header header;
+  vm_buffer_info info;
+  memset(&header, 0, header_size);
+  memset(&info, 0, info_size);
+  struct ioctl_hyper_dmabuf_export_remote msg;
+  char meta_data[header_size + info_size];
+  uint32_t imported_fd = 0;
+
+  header.n_buffers = 1;
+  header.version = 3;
+  header.output = display_index_;
+  header.counter = frame_count_++;
+  header.disp_w = width_;
+  header.disp_h = height_;
+
+  std::shared_ptr<OverlayBuffer> buffer(NULL);
+  uint32_t gpu_fd = resource_manager_->GetNativeBufferHandler()->GetFd();
+  uint32_t id = GetNativeBuffer(gpu_fd, output_handle_);
+  buffer = resource_manager_->FindCachedBuffer(id);
+  const uint32_t *pitches;
+  const uint32_t *offsets;
+
+  if (buffer == NULL) {
+    buffer = OverlayBuffer::CreateOverlayBuffer();
+    buffer->InitializeFromNativeHandle(output_handle_, resource_manager_.get(),
+                                       fb_manager_);
+    resource_manager_->RegisterBuffer(id, buffer);
+    imported_fd = buffer->GetPrimeFD();
+    if (mHyperDmaBuf_Fd > 0 && imported_fd > 0) {
+      mHyperDmaExportedBuffers[imported_fd].width = buffer->GetWidth();
+      mHyperDmaExportedBuffers[imported_fd].height = buffer->GetHeight();
+      mHyperDmaExportedBuffers[imported_fd].format = buffer->GetFormat();
+      pitches = buffer->GetPitches();
+      offsets = buffer->GetOffsets();
+      mHyperDmaExportedBuffers[imported_fd].pitch[0] = pitches[0];
+      mHyperDmaExportedBuffers[imported_fd].pitch[1] = pitches[1];
+      mHyperDmaExportedBuffers[imported_fd].pitch[2] = pitches[2];
+      mHyperDmaExportedBuffers[imported_fd].offset[0] = offsets[0];
+      mHyperDmaExportedBuffers[imported_fd].offset[1] = offsets[1];
+      mHyperDmaExportedBuffers[imported_fd].offset[2] = offsets[2];
+      mHyperDmaExportedBuffers[imported_fd].tile_format =
+          buffer->GetTilingMode();
+      mHyperDmaExportedBuffers[imported_fd].rotation = 0;
+      mHyperDmaExportedBuffers[imported_fd].status = 0;
+      mHyperDmaExportedBuffers[imported_fd].counter = 0;
+      mHyperDmaExportedBuffers[imported_fd].surface_id = display_index_;
+      mHyperDmaExportedBuffers[imported_fd].bbox[0] = 0;
+      mHyperDmaExportedBuffers[imported_fd].bbox[1] = 0;
+      mHyperDmaExportedBuffers[imported_fd].bbox[2] = buffer->GetWidth();
+      mHyperDmaExportedBuffers[imported_fd].bbox[3] = buffer->GetHeight();
+    }
+  }
+
+  msg.sz_priv = header_size + info_size;
+  msg.priv = meta_data;
+
+  /* TODO: add more flexibility here, instead of hardcoded domain 0*/
+  msg.remote_domain = 0;
+  msg.dmabuf_fd = buffer->GetPrimeFD();
+
+  char index[15];
+  mHyperDmaExportedBuffers[buffer->GetPrimeFD()].surf_index = surf_index;
+  memset(index, 0, sizeof(index));
+  sprintf(index, "Cluster_%d", surf_index);
+  strncpy(mHyperDmaExportedBuffers[buffer->GetPrimeFD()].surface_name, index,
+          SURFACE_NAME_LENGTH);
+  mHyperDmaExportedBuffers[buffer->GetPrimeFD()].hyper_dmabuf_id =
+      (hyper_dmabuf_id_t){-1, {-1, -1, -1}};
+  memcpy(meta_data, &header, header_size);
+  memcpy(meta_data + header_size,
+         &mHyperDmaExportedBuffers[buffer->GetPrimeFD()], info_size);
+
+  ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_EXPORT_REMOTE, &msg);
+  if (ret) {
+    ETRACE("Hyper DmaBuf: Exporting hyper_dmabuf failed with error %d\n", ret);
+    return;
+  }
+
+  resource_manager_->PreparePurgedResources();
+
+  std::vector<ResourceHandle> purged_gl_resources;
+  std::vector<MediaResourceHandle> purged_media_resources;
+  bool has_gpu_resource = false;
+
+  resource_manager_->GetPurgedResources(
+      purged_gl_resources, purged_media_resources, &has_gpu_resource);
+
+  size_t purged_size = purged_gl_resources.size();
+
+  if (purged_size != 0) {
+    const NativeBufferHandler *handler =
+        resource_manager_->GetNativeBufferHandler();
+
+    for (size_t i = 0; i < purged_size; i++) {
+      const ResourceHandle &handle = purged_gl_resources.at(i);
+      if (!handle.handle_) {
+        continue;
+      }
+      auto search = mHyperDmaExportedBuffers.find(
+          handle.handle_->imported_handle_->data[0]);
+      if (search != mHyperDmaExportedBuffers.end()) {
+        struct ioctl_hyper_dmabuf_unexport msg;
+        int ret;
+        msg.hid = search->second.hyper_dmabuf_id;
+        msg.delay_ms = 1000;
+        ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_UNEXPORT, &msg);
+        if (ret) {
+          ETRACE(
+              "Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl failed %d "
+              "[0x%x]\n",
+              ret, search->second.hyper_dmabuf_id.id);
+        } else {
+          ITRACE(
+              "Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl Done [0x%x]!\n",
+              search->second.hyper_dmabuf_id.id);
+        }
+        mHyperDmaExportedBuffers.erase(search);
+      }
+      handler->ReleaseBuffer(handle.handle_);
+      handler->DestroyHandle(handle.handle_);
+    }
+  }
+#endif
+}
+
+bool VirtualPanoramaDisplay::Present(std::vector<HwcLayer *> &source_layers,
+                                     int32_t *retire_fence,
+                                     PixelUploaderCallback * /*call_back*/,
+                                     bool handle_constraints) {
+  CTRACE();
+  if (!hyper_dmabuf_initialized) {
+    InitHyperDmaBuf();
+  }
+
+  std::vector<OverlayLayer> layers;
+  std::vector<HwcRect<int>> layers_rects;
+  std::vector<size_t> index;
+  int ret = 0;
+  size_t size = source_layers.size();
+  size_t previous_size = in_flight_layers_.size();
+  bool frame_changed = (size != previous_size);
+  bool layers_changed = frame_changed;
+  *retire_fence = -1;
+  uint32_t z_order = 0;
+
+  resource_manager_->RefreshBufferCache();
+  for (size_t layer_index = 0; layer_index < size; layer_index++) {
+    HwcLayer *layer = source_layers.at(layer_index);
+    layer->SetReleaseFence(-1);
+    if (!layer->IsVisible())
+      continue;
+    if (discard_protected_video_) {
+      if (layer->GetNativeHandle() != NULL &&
+          (layer->GetNativeHandle()->meta_data_.usage_ &
+           hwcomposer::kLayerProtected))
+        continue;
+    }
+
+    layers.emplace_back();
+    OverlayLayer &overlay_layer = layers.back();
+    OverlayLayer *previous_layer = NULL;
+    if (previous_size > z_order) {
+      previous_layer = &(in_flight_layers_.at(z_order));
+    }
+
+    handle_constraints = true;
+
+    overlay_layer.InitializeFromHwcLayer(
+        layer, resource_manager_.get(), previous_layer, z_order, layer_index,
+        height_, kIdentity, handle_constraints, fb_manager_);
+    index.emplace_back(z_order);
+    layers_rects.emplace_back(overlay_layer.GetDisplayFrame());
+
+    z_order++;
+
+    if (frame_changed) {
+      layer->Validate();
+      continue;
+    }
+
+    if (!previous_layer || overlay_layer.HasLayerContentChanged() ||
+        overlay_layer.HasDimensionsChanged()) {
+      layers_changed = true;
+    }
+
+    layer->Validate();
+  }
+
+  if (layers_changed) {
+    compositor_.BeginFrame(false);
+    // Prepare for final composition.
+    if (!compositor_.DrawOffscreen(
+            layers, layers_rects, index, resource_manager_.get(), fb_manager_,
+            width_, height_, output_handle_, acquire_fence_, retire_fence)) {
+      ETRACE("Failed to prepare for the frame composition ret=%d", ret);
+      return false;
+    }
+
+    acquire_fence_ = 0;
+
+    in_flight_layers_.swap(layers);
+  }
+
+  int32_t fence = *retire_fence;
+
+  if (fence > 0) {
+    for (size_t layer_index = 0; layer_index < size; layer_index++) {
+      HwcLayer *layer = source_layers.at(layer_index);
+      layer->SetReleaseFence(dup(fence));
+    }
+  } else {
+    for (size_t layer_index = 0; layer_index < size; layer_index++) {
+      const OverlayLayer &overlay_layer =
+          in_flight_layers_.at(index.at(layer_index));
+      HwcLayer *layer = source_layers.at(overlay_layer.GetLayerIndex());
+      layer->SetReleaseFence(overlay_layer.ReleaseAcquireFence());
+    }
+  }
+  if (resource_manager_->PreparePurgedResources()) {
+    compositor_.FreeResources();
+  }
+
+#ifdef HYPER_DMABUF_SHARING
+  HyperDmaExport();
+#endif
+
+  return true;
+}
+
+void VirtualPanoramaDisplay::CreateOutBuffer() {
+  const NativeBufferHandler *handler =
+      resource_manager_->GetNativeBufferHandler();
+  HWCNativeHandle native_handle = 0;
+  bool modifier_used = false;
+  uint32_t usage = hwcomposer::kLayerNormal;
+
+  handler->CreateBuffer(width_, height_, DRM_FORMAT_BGRA8888, &native_handle,
+                        usage, &modifier_used);
+
+  DTRACE("Create Buffer handler :%p", native_handle);
+  SetOutputBuffer(native_handle, -1);
+}
+
+void VirtualPanoramaDisplay::SetOutputBuffer(HWCNativeHandle buffer,
+                                             int32_t acquire_fence) {
+  if (!output_handle_ || output_handle_ != buffer) {
+    const NativeBufferHandler *handler =
+        resource_manager_->GetNativeBufferHandler();
+
+    if (handle_) {
+      handler->ReleaseBuffer(handle_);
+      handler->DestroyHandle(handle_);
+    }
+
+    delete output_handle_;
+    output_handle_ = buffer;
+    handle_ = 0;
+
+    if (output_handle_) {
+      handler->CopyHandle(output_handle_, &handle_);
+    }
+  }
+
+  if (acquire_fence_ > 0) {
+    close(acquire_fence_);
+    acquire_fence_ = -1;
+  }
+
+  if (acquire_fence > 0) {
+    acquire_fence_ = dup(acquire_fence);
+  }
+}
+
+bool VirtualPanoramaDisplay::Initialize(
+    NativeBufferHandler * /*buffer_manager*/,
+    FrameBufferManager *frame_buffer_manager) {
+  return true;
+}
+
+bool VirtualPanoramaDisplay::GetDisplayAttribute(uint32_t /*config*/,
+                                                 HWCDisplayAttribute attribute,
+                                                 int32_t *value) {
+  // We always get the values from preferred mode config.
+  switch (attribute) {
+    case HWCDisplayAttribute::kWidth:
+      *value = width_;
+      break;
+    case HWCDisplayAttribute::kHeight:
+      *value = height_;
+      break;
+    case HWCDisplayAttribute::kRefreshRate:
+      // in nanoseconds
+      *value = 16666666;
+      break;
+    case HWCDisplayAttribute::kDpiX:
+      // Dots per 1000 inches
+      *value = 1;
+      break;
+    case HWCDisplayAttribute::kDpiY:
+      // Dots per 1000 inches
+      *value = 1;
+      break;
+    default:
+      *value = -1;
+      return false;
+  }
+
+  return true;
+}
+
+bool VirtualPanoramaDisplay::GetDisplayConfigs(uint32_t *num_configs,
+                                               uint32_t *configs) {
+  if (!num_configs)
+    return false;
+  *num_configs = 1;
+  if (configs)
+    configs[0] = 0;
+
+  return true;
+}
+
+bool VirtualPanoramaDisplay::GetDisplayName(uint32_t *size, char *name) {
+  std::ostringstream stream;
+  stream << "Virtual Panorama:" << display_index_;
+  std::string string = stream.str();
+  size_t length = string.length();
+  if (!name) {
+    *size = length;
+    return true;
+  }
+
+  *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
+  strncpy(name, string.c_str(), *size);
+  return true;
+}
+
+int VirtualPanoramaDisplay::GetDisplayPipe() {
+  return -1;
+}
+
+bool VirtualPanoramaDisplay::SetPowerMode(uint32_t /*power_mode*/) {
+  return true;
+}
+
+int VirtualPanoramaDisplay::RegisterVsyncCallback(
+    std::shared_ptr<VsyncCallback> /*callback*/, uint32_t /*display_id*/) {
+  // return 0;
+  return 1;
+}
+
+void VirtualPanoramaDisplay::VSyncControl(bool /*enabled*/) {
+}
+
+bool VirtualPanoramaDisplay::CheckPlaneFormat(uint32_t /*format*/) {
+  // assuming that virtual display supports the format
+  return true;
+}
+}  // namespace hwcomposer
diff --git a/common/display/virtualpanoramadisplay.h b/common/display/virtualpanoramadisplay.h
new file mode 100644 (file)
index 0000000..6326528
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+// Copyright (c) 2016 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef COMMON_DISPLAY_VIRTUALPANORAMADISPLAY_H_
+#define COMMON_DISPLAY_VIRTUALPANORAMADISPLAY_H_
+
+#include <nativedisplay.h>
+
+#include <memory>
+#include <vector>
+
+#include "compositor.h"
+#include "resourcemanager.h"
+#ifdef HYPER_DMABUF_SHARING
+#include "hyperdmadisplay.h"
+#endif
+
+namespace hwcomposer {
+struct HwcLayer;
+class FrameBufferManager;
+class NativeBufferHandler;
+
+class VirtualPanoramaDisplay : public NativeDisplay {
+ public:
+  VirtualPanoramaDisplay(uint32_t gpu_fd, NativeBufferHandler *buffer_handler,
+                         FrameBufferManager *framebuffermanager,
+                         uint32_t pipe_id, uint32_t crtc_id);
+  VirtualPanoramaDisplay(const VirtualPanoramaDisplay &) = delete;
+  VirtualPanoramaDisplay &operator=(const VirtualPanoramaDisplay &) = delete;
+  ~VirtualPanoramaDisplay() override;
+
+  void InitVirtualDisplay(uint32_t width, uint32_t height) override;
+
+  bool GetActiveConfig(uint32_t *config) override;
+
+  bool SetActiveConfig(uint32_t config) override;
+
+  bool Present(std::vector<HwcLayer *> &source_layers, int32_t *retire_fence,
+               PixelUploaderCallback *call_back = NULL,
+               bool handle_constraints = false) override;
+
+  void SetOutputBuffer(HWCNativeHandle buffer, int32_t acquire_fence) override;
+
+  bool Initialize(NativeBufferHandler *buffer_handler,
+                  FrameBufferManager *frame_buffer_manager) override;
+
+  bool IsConnected() const override {
+    return true;
+  }
+
+  void CreateOutBuffer();
+
+  void HyperDmaExport();
+
+  DisplayType Type() const override {
+    return DisplayType::kVirtual;
+  }
+
+  uint32_t Width() const override {
+    return width_;
+  }
+
+  uint32_t Height() const override {
+    return height_;
+  }
+
+  uint32_t PowerMode() const override {
+    return 0;
+  }
+
+  bool GetDisplayAttribute(uint32_t config, HWCDisplayAttribute attribute,
+                           int32_t *value) override;
+
+  bool GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) override;
+  bool GetDisplayName(uint32_t *size, char *name) override;
+  int GetDisplayPipe() override;
+
+  bool SetPowerMode(uint32_t power_mode) override;
+
+  int RegisterVsyncCallback(std::shared_ptr<VsyncCallback> callback,
+                            uint32_t display_id) override;
+
+  void VSyncControl(bool enabled) override;
+  bool CheckPlaneFormat(uint32_t format) override;
+  void SetPAVPSessionStatus(bool enabled, uint32_t pavp_session_id,
+                            uint32_t pavp_instance_id) override {
+    if (enabled) {
+      discard_protected_video_ = false;
+    } else {
+      discard_protected_video_ = true;
+    }
+  }
+
+ private:
+  void InitHyperDmaBuf();
+  HWCNativeHandle output_handle_;
+  int32_t acquire_fence_ = -1;
+  Compositor compositor_;
+  uint32_t width_ = 1;
+  uint32_t height_ = 1;
+  std::vector<OverlayLayer> in_flight_layers_;
+  HWCNativeHandle handle_ = 0;
+  std::unique_ptr<ResourceManager> resource_manager_;
+  FrameBufferManager *fb_manager_ = NULL;
+  uint32_t display_index_ = 0;
+  bool discard_protected_video_ = false;
+  bool hyper_dmabuf_initialized = false;
+
+#ifdef HYPER_DMABUF_SHARING
+  int mHyperDmaBuf_Fd = -1;
+  std::map<uint32_t, vm_buffer_info>
+      mHyperDmaExportedBuffers;  // Track the hyper dmabuf metadata info mapping
+  uint32_t frame_count_ = 0;
+#endif
+};
+
+}  // namespace hwcomposer
+#endif  // COMMON_DISPLAY_VIRTUALMOSAICDISPLAY_H_
index 02564ee..bcc3dff 100644 (file)
@@ -4,6 +4,7 @@ LOGICAL="false"
 MOSAIC="false"
 CLONE="false"
 ROTATION="false"
+PANORAMA="false"
 
 # The Order of Physical Displays. This along with connection status
 # will be used to determine the order. If display is first in this
@@ -25,6 +26,12 @@ LOGICAL_DISPLAY="0:3"
 # sub-display-index: start from 0, should be the available displays number, follow the order of the connected logical displays
 MOSAIC_DISPLAY="0+1+2"
 
+# Panorama display definitions, with format "sub-display-index+sub-display-index+sub-display-index....."
+# sub-display-index: start from 0, should be the available displays number, follow the order of the connected logical displays
+PANORAMA_DISPLAY="0+"
+# Panorama SOS display defines the display index started in SOS side for servering display sharing request from AaaG.
+PANORAMA_SOS_DISPLAY="2+"
+
 # Clone display definitions, with format "physical-display-number:cloned-physical-display-number". This
 # setting is ignored if LOGICAL or MOSAIC is set to true.
 # physical-display-number: start from 0, included all display ports(whatever connected or disconnected)
index b0cd8c7..32f5ccb 100644 (file)
@@ -109,6 +109,20 @@ class GpuDevice : public HWCThread {
   std::unique_ptr<DisplayManager> display_manager_;
   std::vector<std::unique_ptr<LogicalDisplayManager>> logical_display_manager_;
   std::vector<std::unique_ptr<NativeDisplay>> mosaic_displays_;
+#ifdef ENABLE_PANORAMA
+  std::vector<std::unique_ptr<NativeDisplay>> panorama_displays_;
+  void ParsePanoramaDisplayConfig(
+      std::string& value,
+      std::vector<std::vector<uint32_t>>& panorama_displays);
+  void ParsePanoramaSOSDisplayConfig(
+      std::string& value,
+      std::vector<std::vector<uint32_t>>& panorama_sos_displays);
+  void PanoramaInit(std::vector<NativeDisplay*>& total_displays_,
+                    std::vector<NativeDisplay*>& temp_displays,
+                    std::vector<std::vector<uint32_t>>& panorama_displays,
+                    std::vector<std::vector<uint32_t>>& panorama_sos_displays,
+                    std::vector<bool>& available_displays);
+#endif
   std::vector<NativeDisplay*> total_displays_;
 
   bool reserve_plane_ = false;
index bb52058..f2dc0b3 100644 (file)
@@ -302,6 +302,10 @@ struct HwcLayer {
   friend class PhysicalDisplay;
   friend class MosaicDisplay;
 
+#ifdef ENABLE_PANORAMA
+  friend class VirtualPanoramaDisplay;
+#endif
+
   enum LayerState {
     kSurfaceDamageChanged = 1 << 0,
     kLayerContentChanged = 1 << 1,
index a144f7d..8d1039b 100644 (file)
@@ -64,6 +64,10 @@ ifeq ($(strip $(ENABLE_HYPER_DMABUF_SHARING)), true)
 LOCAL_CPPFLAGS += -DHYPER_DMABUF_SHARING
 endif
 
+ifeq ($(strip $(ENABLE_HYPER_DMABUF_SHARING)), true)
+LOCAL_CPPFLAGS += -DENABLE_PANORAMA
+endif
+
 ifeq ($(strip $(TARGET_USES_HWC2)), false)
 LOCAL_C_INCLUDES += \
         system/core/libsync \
index ec71007..d538f2c 100644 (file)
@@ -61,6 +61,11 @@ class DisplayManager {
   virtual NativeDisplay *CreateVirtualDisplay(uint32_t display_index) = 0;
   virtual void DestroyVirtualDisplay(uint32_t display_index) = 0;
 
+#ifdef ENABLE_PANORAMA
+  virtual NativeDisplay *CreateVirtualPanoramaDisplay(
+      uint32_t display_index) = 0;
+#endif
+
   virtual std::vector<NativeDisplay *> GetAllDisplays() = 0;
 
   virtual void RegisterHotPlugEventCallback(
index bde7be7..2822ed1 100644 (file)
@@ -559,4 +559,21 @@ void DrmDisplayManager::RemoveUnreservedPlanes() {
     displays_.at(i)->SetPlanesUpdated(true);
   }
 }
+
+#ifdef ENABLE_PANORAMA
+NativeDisplay *DrmDisplayManager::CreateVirtualPanoramaDisplay(
+    uint32_t display_index) {
+  spin_lock_.lock();
+  NativeDisplay *latest_display;
+  std::unique_ptr<VirtualPanoramaDisplay> display(new VirtualPanoramaDisplay(
+      fd_, buffer_handler_.get(), frame_buffer_manager_.get(), display_index,
+      0));
+  virtual_displays_.emplace_back(std::move(display));
+  size_t size = virtual_displays_.size();
+  latest_display = virtual_displays_.at(size - 1).get();
+  spin_lock_.unlock();
+  return latest_display;
+}
+#endif
+
 }  // namespace hwcomposer
index 3590827..03726c5 100644 (file)
@@ -33,6 +33,9 @@
 #include "hwcthread.h"
 #include "vblankeventhandler.h"
 #include "virtualdisplay.h"
+#ifdef ENABLE_PANORAMA
+#include "virtualpanoramadisplay.h"
+#endif
 
 namespace hwcomposer {
 
@@ -54,6 +57,10 @@ class DrmDisplayManager : public HWCThread, public DisplayManager {
   NativeDisplay *CreateVirtualDisplay(uint32_t display_index) override;
   void DestroyVirtualDisplay(uint32_t display_index) override;
 
+#ifdef ENABLE_PANORAMA
+  NativeDisplay *CreateVirtualPanoramaDisplay(uint32_t display_index) override;
+#endif
+
   std::vector<NativeDisplay *> GetAllDisplays() override;
 
   void RegisterHotPlugEventCallback(