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 \
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 \
}
}
+#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;
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");
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");
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)) {
}
}
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;
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();
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();
}
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();
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
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_;
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_;
};
--- /dev/null
+/*
+// 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_
#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 {
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,
--- /dev/null
+/*
+// 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
--- /dev/null
+/*
+// 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_
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
# 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)
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;
friend class PhysicalDisplay;
friend class MosaicDisplay;
+#ifdef ENABLE_PANORAMA
+ friend class VirtualPanoramaDisplay;
+#endif
+
enum LayerState {
kSurfaceDamageChanged = 1 << 0,
kLayerContentChanged = 1 << 1,
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 \
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(
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
#include "hwcthread.h"
#include "vblankeventhandler.h"
#include "virtualdisplay.h"
+#ifdef ENABLE_PANORAMA
+#include "virtualpanoramadisplay.h"
+#endif
namespace hwcomposer {
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(