summaryrefslogtreecommitdiff
path: root/msm8909/sdm/libs/core/display_base.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'msm8909/sdm/libs/core/display_base.cpp')
-rw-r--r--msm8909/sdm/libs/core/display_base.cpp1536
1 files changed, 1536 insertions, 0 deletions
diff --git a/msm8909/sdm/libs/core/display_base.cpp b/msm8909/sdm/libs/core/display_base.cpp
new file mode 100644
index 00000000..82467379
--- /dev/null
+++ b/msm8909/sdm/libs/core/display_base.cpp
@@ -0,0 +1,1536 @@
+/*
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright notice, this list of
+* conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+* endorse or promote products derived from this software without specific prior written
+* permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/utils.h>
+
+#include <iomanip>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include "display_base.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayBase"
+
+namespace sdm {
+
+// TODO(user): Have a single structure handle carries all the interface pointers and variables.
+DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
+ HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, CompManager *comp_manager,
+ HWInfoInterface *hw_info_intf)
+ : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
+ buffer_sync_handler_(buffer_sync_handler), buffer_allocator_(buffer_allocator),
+ comp_manager_(comp_manager), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayBase::Init() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ hw_panel_info_ = HWPanelInfo();
+ hw_intf_->GetHWPanelInfo(&hw_panel_info_);
+
+ uint32_t active_index = 0;
+ hw_intf_->GetActiveConfig(&active_index);
+ hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
+ fb_config_ = display_attributes_;
+
+ error = Debug::GetMixerResolution(&mixer_attributes_.width, &mixer_attributes_.height);
+ if (error == kErrorNone) {
+ hw_intf_->SetMixerAttributes(mixer_attributes_);
+ }
+
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // Override x_pixels and y_pixels of frame buffer with mixer width and height
+ fb_config_.x_pixels = mixer_attributes_.width;
+ fb_config_.y_pixels = mixer_attributes_.height;
+
+ HWScaleLutInfo lut_info = {};
+ error = comp_manager_->GetScaleLutConfig(&lut_info);
+ if (error == kErrorNone) {
+ error = hw_intf_->SetScaleLutConfig(&lut_info);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+ }
+
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
+ mixer_attributes_, fb_config_, &display_comp_ctx_);
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ if (hw_info_intf_) {
+ HWResourceInfo hw_resource_info = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+ auto max_mixer_stages = hw_resource_info.num_blending_stages;
+ int property_value = Debug::GetMaxPipesPerMixer(display_type_);
+ if (property_value >= 0) {
+ max_mixer_stages = std::min(UINT32(property_value), hw_resource_info.num_blending_stages);
+ }
+ DisplayBase::SetMaxMixerStages(max_mixer_stages);
+ }
+
+ color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
+ display_attributes_, hw_panel_info_);
+ if (!color_mgr_) {
+ DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
+ } else if (InitializeColorModes() != kErrorNone) {
+ DLOGW("InitColorModes failed for display = %d", display_type_);
+ }
+
+ Debug::Get()->GetProperty(DISABLE_HDR_LUT_GEN, &disable_hdr_lut_gen_);
+
+ return kErrorNone;
+
+CleanupOnError:
+ if (display_comp_ctx_) {
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::Deinit() {
+ { // Scope for lock
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ color_modes_.clear();
+ color_mode_map_.clear();
+ color_mode_attr_map_.clear();
+
+ if (color_mgr_) {
+ delete color_mgr_;
+ color_mgr_ = NULL;
+ }
+
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
+ HWEventsInterface::Destroy(hw_events_intf_);
+ HWInterface::Destroy(hw_intf_);
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::BuildLayerStackStats(LayerStack *layer_stack) {
+ std::vector<Layer *> &layers = layer_stack->layers;
+ HWLayersInfo &hw_layers_info = hw_layers_.info;
+
+ hw_layers_info.stack = layer_stack;
+
+ for (auto &layer : layers) {
+ if (layer->composition == kCompositionGPUTarget) {
+ hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
+ break;
+ }
+ hw_layers_info.app_layer_count++;
+ }
+
+ DLOGD_IF(kTagNone, "LayerStack layer_count: %d, app_layer_count: %d, gpu_target_index: %d, "
+ "display type: %d", layers.size(), hw_layers_info.app_layer_count,
+ hw_layers_info.gpu_target_index, display_type_);
+
+ if (!hw_layers_info.app_layer_count) {
+ DLOGW("Layer count is zero");
+ return kErrorNoAppLayers;
+ }
+
+ if (hw_layers_info.gpu_target_index) {
+ return ValidateGPUTargetParams();
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateGPUTargetParams() {
+ HWLayersInfo &hw_layers_info = hw_layers_.info;
+ Layer *gpu_target_layer = hw_layers_info.stack->layers.at(hw_layers_info.gpu_target_index);
+
+ if (!IsValid(gpu_target_layer->src_rect)) {
+ DLOGE("Invalid src rect for GPU target layer");
+ return kErrorParameters;
+ }
+
+ if (!IsValid(gpu_target_layer->dst_rect)) {
+ DLOGE("Invalid dst rect for GPU target layer");
+ return kErrorParameters;
+ }
+
+ float layer_mixer_width = FLOAT(mixer_attributes_.width);
+ float layer_mixer_height = FLOAT(mixer_attributes_.height);
+ float fb_width = FLOAT(fb_config_.x_pixels);
+ float fb_height = FLOAT(fb_config_.y_pixels);
+ LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
+ LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
+ LayerRect out_rect = gpu_target_layer->dst_rect;
+
+ MapRect(src_domain, dst_domain, gpu_target_layer->dst_rect, &out_rect);
+ Normalize(1, 1, &out_rect);
+
+ auto gpu_target_layer_dst_xpixels = out_rect.right - out_rect.left;
+ auto gpu_target_layer_dst_ypixels = out_rect.bottom - out_rect.top;
+
+ if (gpu_target_layer_dst_xpixels > mixer_attributes_.width ||
+ gpu_target_layer_dst_ypixels > mixer_attributes_.height) {
+ DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f, mixer wxh %dx%d",
+ gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels,
+ mixer_attributes_.width, mixer_attributes_.height);
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ needs_validate_ = true;
+
+ if (!active_) {
+ return kErrorPermission;
+ }
+
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
+ DLOGI_IF(kTagDisplay, "Entering Prepare for display type : %d", display_type_);
+ error = BuildLayerStackStats(layer_stack);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = HandleHDR(layer_stack);
+ if (error != kErrorNone) {
+ DLOGW("HandleHDR failed");
+ return error;
+ }
+
+ if (color_mgr_ && color_mgr_->NeedsPartialUpdateDisable()) {
+ DisablePartialUpdateOneFrame();
+ }
+
+ if (partial_update_control_ == false || disable_pu_one_frame_) {
+ comp_manager_->ControlPartialUpdate(display_comp_ctx_, false /* enable */);
+ disable_pu_one_frame_ = false;
+ }
+
+ comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
+ while (true) {
+ error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ break;
+ }
+
+ error = hw_intf_->Validate(&hw_layers_);
+ if (error == kErrorNone) {
+ // Strategy is successful now, wait for Commit().
+ needs_validate_ = false;
+ break;
+ }
+ if (error == kErrorShutDown) {
+ comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+ return error;
+ }
+ }
+
+ comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+
+ DLOGI_IF(kTagDisplay, "Exiting Prepare for display type : %d", display_type_);
+ return error;
+}
+
+DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (!active_) {
+ needs_validate_ = true;
+ return kErrorPermission;
+ }
+
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
+ if (needs_validate_) {
+ DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+ return kErrorNotValidated;
+ }
+
+ // Layer stack attributes has changed, need to Reconfigure, currently in use for Hybrid Comp
+ if (layer_stack->flags.attributes_changed) {
+ error = comp_manager_->ReConfigure(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->Validate(&hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+
+ DLOGI_IF(kTagDisplay, "Entering commit for display type : %d", display_type_);
+ CommitLayerParams(layer_stack);
+
+ error = comp_manager_->Commit(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ // check if feature list cache is dirty and pending.
+ // If dirty, need program to hardware blocks.
+ if (color_mgr_)
+ error = color_mgr_->Commit();
+ if (error != kErrorNone) { // won't affect this execution path.
+ DLOGW("ColorManager::Commit(...) isn't working");
+ }
+
+ error = hw_intf_->Commit(&hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ PostCommitLayerParams(layer_stack);
+
+ if (partial_update_control_) {
+ comp_manager_->ControlPartialUpdate(display_comp_ctx_, true /* enable */);
+ }
+
+ error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ DLOGI_IF(kTagDisplay, "Exiting commit for display type : %d", display_type_);
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::Flush() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (!active_) {
+ return kErrorPermission;
+ }
+ hw_layers_.info.hw_layers.clear();
+ error = hw_intf_->Flush();
+ if (error == kErrorNone) {
+ comp_manager_->Purge(display_comp_ctx_);
+ needs_validate_ = true;
+ } else {
+ DLOGW("Unable to flush display = %d", display_type_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!state) {
+ return kErrorParameters;
+ }
+
+ *state = state_;
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->GetNumDisplayAttributes(count);
+}
+
+DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ HWDisplayAttributes attrib;
+ if (hw_intf_->GetDisplayAttributes(index, &attrib) == kErrorNone) {
+ *variable_info = attrib;
+ return kErrorNone;
+ }
+
+ return kErrorNotSupported;
+}
+
+DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ fixed_info->is_cmdmode = (hw_panel_info_.mode == kModeCommand);
+
+ HWResourceInfo hw_resource_info = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+ // hdr can be supported by display when target and panel supports HDR.
+ fixed_info->hdr_supported = (hw_resource_info.has_hdr && hw_panel_info_.hdr_enabled);
+ // Populate luminance values only if hdr will be supported on that display
+ fixed_info->max_luminance = fixed_info->hdr_supported ? hw_panel_info_.peak_luminance: 0;
+ fixed_info->average_luminance = fixed_info->hdr_supported ? hw_panel_info_.average_luminance : 0;
+ fixed_info->min_luminance = fixed_info->hdr_supported ? hw_panel_info_.blackness_level: 0;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ return hw_intf_->GetActiveConfig(index);
+}
+
+DisplayError DisplayBase::GetVSyncState(bool *enabled) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!enabled) {
+ return kErrorParameters;
+ }
+
+ *enabled = vsync_enable_;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetDisplayState(DisplayState state) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ bool active = false;
+
+ DLOGI("Set state = %d, display %d", state, display_type_);
+
+ if (state == state_) {
+ DLOGI("Same state transition is requested.");
+ return kErrorNone;
+ }
+
+ switch (state) {
+ case kStateOff:
+ hw_layers_.info.hw_layers.clear();
+ error = hw_intf_->Flush();
+ if (error == kErrorNone) {
+ error = hw_intf_->PowerOff();
+ }
+ break;
+
+ case kStateOn:
+ error = hw_intf_->PowerOn();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_,
+ hw_panel_info_, mixer_attributes_, fb_config_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ active = true;
+ break;
+
+ case kStateDoze:
+ error = hw_intf_->Doze();
+ active = true;
+ break;
+
+ case kStateDozeSuspend:
+ error = hw_intf_->DozeSuspend();
+ if (display_type_ != kPrimary) {
+ active = true;
+ }
+
+ break;
+
+ case kStateStandby:
+ error = hw_intf_->Standby();
+ break;
+
+ default:
+ DLOGE("Spurious state = %d transition requested.", state);
+ break;
+ }
+
+ if (error == kErrorNone) {
+ active_ = active;
+ state_ = state;
+ comp_manager_->SetDisplayState(display_comp_ctx_, state, display_type_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ uint32_t active_index = 0;
+
+ hw_intf_->GetActiveConfig(&active_index);
+
+ if (active_index == index) {
+ return kErrorNone;
+ }
+
+ error = hw_intf_->SetDisplayAttributes(index);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return ReconfigureDisplay();
+}
+
+DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ error = comp_manager_->SetMaxMixerStages(display_comp_ctx_, max_mixer_stages);
+
+ if (error == kErrorNone) {
+ max_mixer_stages_ = max_mixer_stages;
+ }
+
+ return error;
+}
+
+std::string DisplayBase::Dump() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ HWDisplayAttributes attrib;
+ uint32_t active_index = 0;
+ uint32_t num_modes = 0;
+ std::ostringstream os;
+
+ hw_intf_->GetNumDisplayAttributes(&num_modes);
+ hw_intf_->GetActiveConfig(&active_index);
+ hw_intf_->GetDisplayAttributes(active_index, &attrib);
+
+ os << "device type:" << display_type_;
+ os << "\nstate: " << state_ << " vsync on: " << vsync_enable_ << " max. mixer stages: "
+ << max_mixer_stages_;
+ os << "\nnum configs: " << num_modes << " active config index: " << active_index;
+
+ DisplayConfigVariableInfo &info = attrib;
+
+ uint32_t num_hw_layers = UINT32(hw_layers_.info.hw_layers.size());
+
+ if (num_hw_layers == 0) {
+ os << "\nNo hardware layers programmed";
+ return os.str();
+ }
+
+ LayerBuffer *out_buffer = nullptr;
+ if (hw_layers_.info.stack) {
+ out_buffer = hw_layers_.info.stack->output_buffer;
+ }
+ if (out_buffer != nullptr) {
+ os << "\nres: " << out_buffer->width << "x" << out_buffer->height << " format: "
+ << GetFormatString(out_buffer->format);
+ } else {
+ os.precision(2);
+ os << "\nres: " << info.x_pixels << "x" << info.y_pixels << " dpi: " << std::fixed <<
+ info.x_dpi << "x" << std::fixed << info.y_dpi << " fps: " << info.fps <<
+ " vsync period: " << info.vsync_period_ns;
+ }
+
+ HWLayersInfo &layer_info = hw_layers_.info;
+ for (uint32_t i = 0; i < layer_info.left_frame_roi.size(); i++) {
+ LayerRect &l_roi = layer_info.left_frame_roi.at(i);
+ LayerRect &r_roi = layer_info.right_frame_roi.at(i);
+
+ os << "\nROI(LTRB)#" << i << " LEFT(" << INT(l_roi.left) << " " << INT(l_roi.top) << " " <<
+ INT(l_roi.right) << " " << INT(l_roi.bottom) << ")";
+ if (IsValid(r_roi)) {
+ os << " RIGHT(" << INT(r_roi.left) << " " << INT(r_roi.top) << " " << INT(r_roi.right) << " "
+ << INT(r_roi.bottom) << ")";
+ }
+ }
+
+ LayerRect &fb_roi = layer_info.partial_fb_roi;
+ if (IsValid(fb_roi)) {
+ os << "\nPartial FB ROI(LTRB):(" << INT(fb_roi.left) << " " << INT(fb_roi.top) << " " <<
+ INT(fb_roi.right) << " " << INT(fb_roi.bottom) << ")";
+ }
+
+ const char *header = "\n| Idx | Comp Type | Split | WB | Pipe | W x H | Format | Src Rect (L T R B) | Dst Rect (L T R B) | Z | Flags | Deci(HxV) | CS | Rng |"; //NOLINT
+ const char *newline = "\n|-----|-------------|--------|----|--------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|-----|"; //NOLINT
+ const char *format = "\n| %3s | %11s " "| %6s " "| %2s | 0x%04x | %4d x %4d | %24s " "| %4d %4d %4d %4d " "| %4d %4d %4d %4d " "| %2s | %10s " "| %9s | %2s | %3s |"; //NOLINT
+
+
+ os << "\n";
+ os << newline;
+ os << header;
+ os << newline;
+
+ for (uint32_t i = 0; i < num_hw_layers; i++) {
+ uint32_t layer_index = hw_layers_.info.index[i];
+ // hw-layer from hw layers info
+ Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+ LayerBuffer *input_buffer = &hw_layer.input_buffer;
+ HWLayerConfig &layer_config = hw_layers_.config[i];
+ HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
+
+ char idx[8] = { 0 };
+ const char *comp_type = GetName(hw_layer.composition);
+ const char *buffer_format = GetFormatString(input_buffer->format);
+ const char *rotate_split[2] = { "Rot-1", "Rot-2" };
+ const char *comp_split[2] = { "Comp-1", "Comp-2" };
+
+ snprintf(idx, sizeof(idx), "%d", layer_index);
+
+ for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
+ char writeback_id[8] = { 0 };
+ char row[1024];
+ HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
+ LayerRect &src_roi = rotate.src_roi;
+ LayerRect &dst_roi = rotate.dst_roi;
+
+ snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
+
+ snprintf(row, sizeof(row), format, idx, comp_type, rotate_split[count],
+ writeback_id, rotate.pipe_id, input_buffer->width,
+ input_buffer->height, buffer_format, INT(src_roi.left),
+ INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
+ INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
+ INT(dst_roi.bottom), "-", "- ", "- ", "-", "-");
+ os << row;
+ // print the below only once per layer block, fill with spaces for rest.
+ idx[0] = 0;
+ comp_type = "";
+ }
+
+ if (hw_rotator_session.hw_block_count > 0) {
+ input_buffer = &hw_rotator_session.output_buffer;
+ buffer_format = GetFormatString(input_buffer->format);
+ }
+
+ for (uint32_t count = 0; count < 2; count++) {
+ char decimation[16] = { 0 };
+ char flags[16] = { 0 };
+ char z_order[8] = { 0 };
+ char color_primary[8] = { 0 };
+ char range[8] = { 0 };
+
+ HWPipeInfo &pipe = (count == 0) ? layer_config.left_pipe : layer_config.right_pipe;
+
+ if (!pipe.valid) {
+ continue;
+ }
+
+ LayerRect &src_roi = pipe.src_roi;
+ LayerRect &dst_roi = pipe.dst_roi;
+
+ snprintf(z_order, sizeof(z_order), "%d", pipe.z_order);
+ snprintf(flags, sizeof(flags), "0x%08x", hw_layer.flags.flags);
+ snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation,
+ pipe.vertical_decimation);
+ ColorMetaData &color_metadata = hw_layer.input_buffer.color_metadata;
+ snprintf(color_primary, sizeof(color_primary), "%d", color_metadata.colorPrimaries);
+ snprintf(range, sizeof(range), "%d", color_metadata.range);
+
+ char row[1024];
+ snprintf(row, sizeof(row), format, idx, comp_type, comp_split[count],
+ "-", pipe.pipe_id, input_buffer->width, input_buffer->height,
+ buffer_format, INT(src_roi.left), INT(src_roi.top),
+ INT(src_roi.right), INT(src_roi.bottom), INT(dst_roi.left),
+ INT(dst_roi.top), INT(dst_roi.right), INT(dst_roi.bottom),
+ z_order, flags, decimation, color_primary, range);
+
+ os << row;
+ // print the below only once per layer block, fill with spaces for rest.
+ idx[0] = 0;
+ comp_type = "";
+ }
+ }
+
+ os << newline << "\n";
+
+ return os.str();
+}
+
+const char * DisplayBase::GetName(const LayerComposition &composition) {
+ switch (composition) {
+ case kCompositionGPU: return "GPU";
+ case kCompositionSDE: return "SDE";
+ case kCompositionHWCursor: return "CURSOR";
+ case kCompositionHybrid: return "HYBRID";
+ case kCompositionBlit: return "BLIT";
+ case kCompositionGPUTarget: return "GPU_TARGET";
+ case kCompositionBlitTarget: return "BLIT_TARGET";
+ default: return "UNKNOWN";
+ }
+}
+
+DisplayError DisplayBase::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+ PPDisplayAPIPayload *out_payload,
+ PPPendingParams *pending_action) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (color_mgr_)
+ return color_mgr_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
+ else
+ return kErrorParameters;
+}
+
+DisplayError DisplayBase::GetColorModeCount(uint32_t *mode_count) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!mode_count) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ DLOGV_IF(kTagQDCM, "Number of modes from color manager = %d", num_color_modes_);
+ *mode_count = num_color_modes_;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetColorModes(uint32_t *mode_count,
+ std::vector<std::string> *color_modes) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!mode_count || !color_modes) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ for (uint32_t i = 0; i < num_color_modes_; i++) {
+ DLOGV_IF(kTagQDCM, "Color Mode[%d]: Name = %s mode_id = %d", i, color_modes_[i].name,
+ color_modes_[i].id);
+ color_modes->at(i) = color_modes_[i].name;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetColorModeAttr(const std::string &color_mode, AttrVal *attr) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!attr) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ auto it = color_mode_attr_map_.find(color_mode);
+ if (it == color_mode_attr_map_.end()) {
+ DLOGE("Failed: Mode %s without attribute", color_mode.c_str());
+ return kErrorNotSupported;
+ }
+ *attr = it->second;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetColorMode(const std::string &color_mode) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ DynamicRangeType dynamic_range_type;
+ if (IsSupportColorModeAttribute(color_mode)) {
+ auto it_mode = color_mode_attr_map_.find(color_mode);
+ std::string dynamic_range;
+ GetValueOfModeAttribute(it_mode->second, kDynamicRangeAttribute, &dynamic_range);
+ if (dynamic_range == kHdr) {
+ dynamic_range_type = kHdrType;
+ } else {
+ dynamic_range_type = kSdrType;
+ }
+ } else {
+ if (color_mode.find("hal_hdr") != std::string::npos) {
+ dynamic_range_type = kHdrType;
+ } else {
+ dynamic_range_type = kSdrType;
+ }
+ }
+
+ DisplayError error = kErrorNone;
+ if (disable_hdr_lut_gen_) {
+ error = SetColorModeInternal(color_mode);
+ if (error != kErrorNone) {
+ return error;
+ }
+ // Store the new SDR color mode request by client
+ if (dynamic_range_type == kSdrType) {
+ current_color_mode_ = color_mode;
+ }
+ return error;
+ }
+
+ if (hdr_playback_mode_) {
+ // HDR playback on, If incoming mode is SDR mode,
+ // cache the mode and apply it after HDR playback stop.
+ if (dynamic_range_type == kHdrType) {
+ error = SetColorModeInternal(color_mode);
+ if (error != kErrorNone) {
+ return error;
+ }
+ } else if (dynamic_range_type == kSdrType) {
+ current_color_mode_ = color_mode;
+ }
+ } else {
+ // HDR playback off, do not apply HDR mode
+ if (dynamic_range_type == kHdrType) {
+ DLOGE("Failed: Forbid setting HDR Mode : %s when HDR playback off", color_mode.c_str());
+ return kErrorNotSupported;
+ }
+ error = SetColorModeInternal(color_mode);
+ if (error != kErrorNone) {
+ return error;
+ }
+ current_color_mode_ = color_mode;
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::SetColorModeInternal(const std::string &color_mode) {
+ DLOGV_IF(kTagQDCM, "Color Mode = %s", color_mode.c_str());
+
+ ColorModeMap::iterator it = color_mode_map_.find(color_mode);
+ if (it == color_mode_map_.end()) {
+ DLOGE("Failed: Unknown Mode : %s", color_mode.c_str());
+ return kErrorNotSupported;
+ }
+
+ SDEDisplayMode *sde_display_mode = it->second;
+
+ DLOGV_IF(kTagQDCM, "Color Mode Name = %s corresponding mode_id = %d", sde_display_mode->name,
+ sde_display_mode->id);
+ DisplayError error = kErrorNone;
+ error = color_mgr_->ColorMgrSetMode(sde_display_mode->id);
+ if (error != kErrorNone) {
+ DLOGE("Failed for mode id = %d", sde_display_mode->id);
+ return error;
+ }
+
+ return error;
+}
+
+DisplayError DisplayBase::GetValueOfModeAttribute(const AttrVal &attr,const std::string &type,
+ std::string *value) {
+ if (!value) {
+ return kErrorParameters;
+ }
+ for (auto &it : attr) {
+ if (it.first.find(type) != std::string::npos) {
+ *value = it.second;
+ }
+ }
+
+ return kErrorNone;
+}
+
+bool DisplayBase::IsSupportColorModeAttribute(const std::string &color_mode) {
+ auto it = color_mode_attr_map_.find(color_mode);
+ if (it == color_mode_attr_map_.end()) {
+ return false;
+ }
+ return true;
+}
+
+DisplayError DisplayBase::GetHdrColorMode(std::string *color_mode, bool *found_hdr) {
+ if (!found_hdr || !color_mode) {
+ return kErrorParameters;
+ }
+ auto it_mode = color_mode_attr_map_.find(current_color_mode_);
+ if (it_mode == color_mode_attr_map_.end()) {
+ DLOGE("Failed: Unknown Mode : %s", current_color_mode_.c_str());
+ return kErrorNotSupported;
+ }
+
+ *found_hdr = false;
+ std::string cur_color_gamut, cur_pic_quality;
+ // get the attributes of current color mode
+ GetValueOfModeAttribute(it_mode->second, kColorGamutAttribute, &cur_color_gamut);
+ GetValueOfModeAttribute(it_mode->second, kPictureQualityAttribute, &cur_pic_quality);
+
+ // found the corresponding HDR mode id which
+ // has the same attributes with current SDR mode.
+ for (auto &it_hdr : color_mode_attr_map_) {
+ std::string dynamic_range, color_gamut, pic_quality;
+ GetValueOfModeAttribute(it_hdr.second, kDynamicRangeAttribute, &dynamic_range);
+ GetValueOfModeAttribute(it_hdr.second, kColorGamutAttribute, &color_gamut);
+ GetValueOfModeAttribute(it_hdr.second, kPictureQualityAttribute, &pic_quality);
+ if (dynamic_range == kHdr && cur_color_gamut == color_gamut &&
+ cur_pic_quality == pic_quality) {
+ *color_mode = it_hdr.first;
+ *found_hdr = true;
+ DLOGV_IF(kTagQDCM, "corresponding hdr mode = %s", color_mode->c_str());
+ return kErrorNone;
+ }
+ }
+
+ // The corresponding HDR mode was not be found,
+ // apply the first HDR mode that we encouter.
+ for (auto &it_hdr : color_mode_attr_map_) {
+ std::string dynamic_range;
+ GetValueOfModeAttribute(it_hdr.second, kDynamicRangeAttribute, &dynamic_range);
+ if (dynamic_range == kHdr) {
+ *color_mode = it_hdr.first;
+ *found_hdr = true;
+ DLOGV_IF(kTagQDCM, "First hdr mode = %s", color_mode->c_str());
+ return kErrorNone;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetColorTransform(const uint32_t length, const double *color_transform) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ if (!color_transform) {
+ return kErrorParameters;
+ }
+
+ return color_mgr_->ColorMgrSetColorTransform(length, color_transform);
+}
+
+DisplayError DisplayBase::GetDefaultColorMode(std::string *color_mode) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!color_mode) {
+ return kErrorParameters;
+ }
+
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ int32_t default_id = kInvalidModeId;
+ DisplayError error = color_mgr_->ColorMgrGetDefaultModeID(&default_id);
+ if (error != kErrorNone) {
+ DLOGE("Failed for get default color mode id");
+ return error;
+ }
+
+ for (uint32_t i = 0; i < num_color_modes_; i++) {
+ if (color_modes_[i].id == default_id) {
+ *color_mode = color_modes_[i].name;
+ return kErrorNone;
+ }
+ }
+
+ return kErrorNotSupported;
+}
+
+DisplayError DisplayBase::ApplyDefaultDisplayMode() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (color_mgr_)
+ return color_mgr_->ApplyDefaultDisplayMode();
+ else
+ return kErrorParameters;
+}
+
+DisplayError DisplayBase::SetCursorPosition(int x, int y) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (state_ != kStateOn) {
+ return kErrorNotSupported;
+ }
+
+ DisplayError error = comp_manager_->ValidateAndSetCursorPosition(display_comp_ctx_, &hw_layers_,
+ x, y);
+ if (error == kErrorNone) {
+ return hw_intf_->SetCursorPosition(&hw_layers_, x, y);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetRefreshRateRange(uint32_t *min_refresh_rate,
+ uint32_t *max_refresh_rate) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ // The min and max refresh rates will be same when the HWPanelInfo does not contain valid rates.
+ // Usually for secondary displays, command mode panels
+ HWDisplayAttributes display_attributes;
+ uint32_t active_index = 0;
+ hw_intf_->GetActiveConfig(&active_index);
+ DisplayError error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+ if (error) {
+ return error;
+ }
+
+ *min_refresh_rate = display_attributes.fps;
+ *max_refresh_rate = display_attributes.fps;
+
+ return error;
+}
+
+DisplayError DisplayBase::SetVSyncState(bool enable) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ if (vsync_enable_ != enable) {
+ error = hw_intf_->SetVSyncState(enable);
+ if (error == kErrorNone) {
+ vsync_enable_ = enable;
+ }
+ }
+ return error;
+}
+
+DisplayError DisplayBase::ReconfigureDisplay() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ HWDisplayAttributes display_attributes;
+ HWMixerAttributes mixer_attributes;
+ HWPanelInfo hw_panel_info;
+ uint32_t active_index = 0;
+
+ error = hw_intf_->GetActiveConfig(&active_index);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetHWPanelInfo(&hw_panel_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (display_attributes == display_attributes_ && mixer_attributes == mixer_attributes_ &&
+ hw_panel_info == hw_panel_info_) {
+ return kErrorNone;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+ mixer_attributes, fb_config_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ if (mixer_attributes != mixer_attributes_) {
+ DisablePartialUpdateOneFrame();
+ }
+
+ display_attributes_ = display_attributes;
+ mixer_attributes_ = mixer_attributes;
+ hw_panel_info_ = hw_panel_info;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetMixerResolution(uint32_t width, uint32_t height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ DisplayError error = ReconfigureMixer(width, height);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ req_mixer_width_ = width;
+ req_mixer_height_ = height;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!width || !height) {
+ return kErrorParameters;
+ }
+
+ *width = mixer_attributes_.width;
+ *height = mixer_attributes_.height;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ReconfigureMixer(uint32_t width, uint32_t height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+
+ if (!width || !height) {
+ return kErrorParameters;
+ }
+
+ DLOGD_IF(kTagQDCM, "Reconfiguring mixer with width : %d, height : %d", width, height);
+ HWMixerAttributes mixer_attributes;
+ mixer_attributes.width = width;
+ mixer_attributes.height = height;
+
+ error = hw_intf_->SetMixerAttributes(mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return ReconfigureDisplay();
+}
+
+bool DisplayBase::NeedsDownScale(const LayerRect &src_rect, const LayerRect &dst_rect,
+ bool needs_rotation) {
+ float src_width = FLOAT(src_rect.right - src_rect.left);
+ float src_height = FLOAT(src_rect.bottom - src_rect.top);
+ float dst_width = FLOAT(dst_rect.right - dst_rect.left);
+ float dst_height = FLOAT(dst_rect.bottom - dst_rect.top);
+
+ if (needs_rotation) {
+ std::swap(src_width, src_height);
+ }
+
+ if ((src_width > dst_width) || (src_height > dst_height)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool DisplayBase::NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+ uint32_t *new_mixer_height) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ uint32_t layer_count = UINT32(layer_stack->layers.size());
+
+ uint32_t fb_width = fb_config_.x_pixels;
+ uint32_t fb_height = fb_config_.y_pixels;
+ uint32_t fb_area = fb_width * fb_height;
+ LayerRect fb_rect = (LayerRect) {0.0f, 0.0f, FLOAT(fb_width), FLOAT(fb_height)};
+ uint32_t mixer_width = mixer_attributes_.width;
+ uint32_t mixer_height = mixer_attributes_.height;
+ uint32_t display_width = display_attributes_.x_pixels;
+ uint32_t display_height = display_attributes_.y_pixels;
+
+ RectOrientation fb_orientation = GetOrientation(fb_rect);
+ uint32_t max_layer_area = 0;
+ uint32_t max_area_layer_index = 0;
+ std::vector<Layer *> layers = layer_stack->layers;
+ uint32_t align_x = display_attributes_.is_device_split ? 4 : 2;
+ uint32_t align_y = 2;
+
+ if (req_mixer_width_ && req_mixer_height_) {
+ DLOGD_IF(kTagDisplay, "Required mixer width : %d, height : %d",
+ req_mixer_width_, req_mixer_height_);
+ *new_mixer_width = req_mixer_width_;
+ *new_mixer_height = req_mixer_height_;
+ return (req_mixer_width_ != mixer_width || req_mixer_height_ != mixer_height);
+ }
+
+ for (uint32_t i = 0; i < layer_count; i++) {
+ Layer *layer = layers.at(i);
+
+ uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+ uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+ uint32_t layer_area = layer_width * layer_height;
+
+ if (layer_area > max_layer_area) {
+ max_layer_area = layer_area;
+ max_area_layer_index = i;
+ }
+ }
+ DLOGV_IF(kTagDisplay, "Max area layer at index : %d", max_area_layer_index);
+
+ // TODO(user): Mark layer which needs downscaling on GPU fallback as priority layer and use MDP
+ // for composition to avoid quality mismatch between GPU and MDP switch(idle timeout usecase).
+ if (max_layer_area >= fb_area) {
+ Layer *layer = layers.at(max_area_layer_index);
+ bool needs_rotation = (layer->transform.rotation == 90.0f);
+
+ uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+ uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+ LayerRect layer_dst_rect = {};
+
+ RectOrientation layer_orientation = GetOrientation(layer->src_rect);
+ if (layer_orientation != kOrientationUnknown &&
+ fb_orientation != kOrientationUnknown) {
+ if (layer_orientation != fb_orientation) {
+ std::swap(layer_width, layer_height);
+ }
+ }
+
+ // Align the width and height according to fb's aspect ratio
+ *new_mixer_width = FloorToMultipleOf(UINT32((FLOAT(fb_width) / FLOAT(fb_height)) *
+ layer_height), align_x);
+ *new_mixer_height = FloorToMultipleOf(layer_height, align_y);
+
+ LayerRect dst_domain = {0.0f, 0.0f, FLOAT(*new_mixer_width), FLOAT(*new_mixer_height)};
+
+ MapRect(fb_rect, dst_domain, layer->dst_rect, &layer_dst_rect);
+ if (NeedsDownScale(layer->src_rect, layer_dst_rect, needs_rotation)) {
+ *new_mixer_width = display_width;
+ *new_mixer_height = display_height;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+DisplayError DisplayBase::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ uint32_t width = variable_info.x_pixels;
+ uint32_t height = variable_info.y_pixels;
+
+ if (width == 0 || height == 0) {
+ DLOGE("Unsupported resolution: (%dx%d)", width, height);
+ return kErrorParameters;
+ }
+
+ // Create rects to represent the new source and destination crops
+ LayerRect crop = LayerRect(0, 0, FLOAT(width), FLOAT(height));
+ LayerRect dst = LayerRect(0, 0, FLOAT(mixer_attributes_.width), FLOAT(mixer_attributes_.height));
+ // Set rotate90 to false since this is taken care of during regular composition.
+ bool rotate90 = false;
+
+ DisplayError error = comp_manager_->ValidateScaling(crop, dst, rotate90);
+ if (error != kErrorNone) {
+ DLOGE("Unsupported resolution: (%dx%d)", width, height);
+ return kErrorParameters;
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_, hw_panel_info_,
+ mixer_attributes_, variable_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ fb_config_.x_pixels = width;
+ fb_config_.y_pixels = height;
+
+ DLOGI("New framebuffer resolution (%dx%d)", fb_config_.x_pixels, fb_config_.y_pixels);
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
+ *variable_info = fb_config_;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = comp_manager_->SetDetailEnhancerData(display_comp_ctx_, de_data);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ DisablePartialUpdateOneFrame();
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::GetDisplayPort(DisplayPort *port) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ if (!port) {
+ return kErrorParameters;
+ }
+
+ *port = hw_panel_info_.port;
+
+ return kErrorNone;
+}
+
+bool DisplayBase::IsPrimaryDisplay() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ return hw_panel_info_.is_primary_panel;
+}
+
+DisplayError DisplayBase::SetCompositionState(LayerComposition composition_type, bool enable) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+ return comp_manager_->SetCompositionState(display_comp_ctx_, composition_type, enable);
+}
+
+void DisplayBase::CommitLayerParams(LayerStack *layer_stack) {
+ // Copy the acquire fence from clients layers to HWLayers
+ uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
+
+ for (uint32_t i = 0; i < hw_layers_count; i++) {
+ Layer *sdm_layer = layer_stack->layers.at(hw_layers_.info.index[i]);
+ Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+
+ hw_layer.input_buffer.planes[0].fd = sdm_layer->input_buffer.planes[0].fd;
+ hw_layer.input_buffer.planes[0].offset = sdm_layer->input_buffer.planes[0].offset;
+ hw_layer.input_buffer.planes[0].stride = sdm_layer->input_buffer.planes[0].stride;
+ hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
+ hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
+ }
+
+ return;
+}
+
+void DisplayBase::PostCommitLayerParams(LayerStack *layer_stack) {
+ // Copy the release fence from HWLayers to clients layers
+ uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
+
+ std::vector<uint32_t> fence_dup_flag;
+
+ for (uint32_t i = 0; i < hw_layers_count; i++) {
+ uint32_t sdm_layer_index = hw_layers_.info.index[i];
+ Layer *sdm_layer = layer_stack->layers.at(sdm_layer_index);
+ Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+
+ // Copy the release fence only once for a SDM Layer.
+ // In S3D use case, two hw layers can share the same input buffer, So make sure to merge the
+ // output fence fd and assign it to layer's input buffer release fence fd.
+ if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), sdm_layer_index) ==
+ fence_dup_flag.end()) {
+ sdm_layer->input_buffer.release_fence_fd = hw_layer.input_buffer.release_fence_fd;
+ fence_dup_flag.push_back(sdm_layer_index);
+ } else {
+ int temp = -1;
+ buffer_sync_handler_->SyncMerge(hw_layer.input_buffer.release_fence_fd,
+ sdm_layer->input_buffer.release_fence_fd, &temp);
+
+ if (hw_layer.input_buffer.release_fence_fd >= 0) {
+ Sys::close_(hw_layer.input_buffer.release_fence_fd);
+ hw_layer.input_buffer.release_fence_fd = -1;
+ }
+
+ if (sdm_layer->input_buffer.release_fence_fd >= 0) {
+ Sys::close_(sdm_layer->input_buffer.release_fence_fd);
+ sdm_layer->input_buffer.release_fence_fd = -1;
+ }
+
+ sdm_layer->input_buffer.release_fence_fd = temp;
+ }
+ }
+
+ return;
+}
+
+DisplayError DisplayBase::InitializeColorModes() {
+ if (!color_mgr_) {
+ return kErrorNotSupported;
+ }
+
+ DisplayError error = color_mgr_->ColorMgrGetNumOfModes(&num_color_modes_);
+ if (error != kErrorNone || !num_color_modes_) {
+ DLOGV_IF(kTagQDCM, "GetNumModes failed = %d count = %d", error, num_color_modes_);
+ return kErrorNotSupported;
+ }
+ DLOGI("Number of Color Modes = %d", num_color_modes_);
+
+ if (!color_modes_.size()) {
+ color_modes_.resize(num_color_modes_);
+
+ DisplayError error = color_mgr_->ColorMgrGetModes(&num_color_modes_, color_modes_.data());
+ if (error != kErrorNone) {
+ color_modes_.clear();
+ DLOGE("Failed");
+ return error;
+ }
+ int32_t default_id = kInvalidModeId;
+ error = color_mgr_->ColorMgrGetDefaultModeID(&default_id);
+
+ AttrVal var;
+ for (uint32_t i = 0; i < num_color_modes_; i++) {
+ DLOGV_IF(kTagQDCM, "Color Mode[%d]: Name = %s mode_id = %d", i, color_modes_[i].name,
+ color_modes_[i].id);
+ // get the name of default color mode
+ if (color_modes_[i].id == default_id) {
+ current_color_mode_ = color_modes_[i].name;
+ }
+ auto it = color_mode_map_.find(color_modes_[i].name);
+ if (it != color_mode_map_.end()) {
+ if (it->second->id < color_modes_[i].id) {
+ color_mode_map_.erase(it);
+ color_mode_map_.insert(std::make_pair(color_modes_[i].name, &color_modes_[i]));
+ }
+ } else {
+ color_mode_map_.insert(std::make_pair(color_modes_[i].name, &color_modes_[i]));
+ }
+
+ var.clear();
+ error = color_mgr_->ColorMgrGetModeInfo(color_modes_[i].id, &var);
+ if (error != kErrorNone) {
+ DLOGE("Failed for get attributes of mode_id = %d", color_modes_[i].id);
+ continue;
+ }
+ if (!var.empty()) {
+ auto it = color_mode_attr_map_.find(color_modes_[i].name);
+ if (it == color_mode_attr_map_.end()) {
+ color_mode_attr_map_.insert(std::make_pair(color_modes_[i].name, var));
+ }
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::HandleHDR(LayerStack *layer_stack) {
+ DisplayError error = kErrorNone;
+
+ if (display_type_ != kPrimary) {
+ // Handling is needed for only primary displays
+ return kErrorNone;
+ }
+
+ if (!layer_stack->flags.hdr_present) {
+ // HDR playback off - set prev mode
+ if (hdr_playback_mode_) {
+ hdr_playback_mode_ = false;
+ if (color_mgr_ && !disable_hdr_lut_gen_) {
+ // Do not apply HDR Mode when hdr lut generation is disabled
+ DLOGI("Setting color mode = %s", current_color_mode_.c_str());
+ // HDR playback off - set prev mode
+ error = SetColorModeInternal(current_color_mode_);
+ }
+ comp_manager_->ControlDpps(true); // Enable Dpps
+ }
+ } else {
+ // hdr is present
+ if (!hdr_playback_mode_ && !layer_stack->flags.animating) {
+ // hdr is starting
+ hdr_playback_mode_ = true;
+ if (color_mgr_ && !disable_hdr_lut_gen_) {
+ std::string hdr_color_mode;
+ if (IsSupportColorModeAttribute(current_color_mode_)) {
+ bool found_hdr = false;
+ error = GetHdrColorMode(&hdr_color_mode, &found_hdr);
+ // try to set "hal-hdr" mode if did not found that
+ // the dynamic range of mode is hdr
+ if (!found_hdr) {
+ hdr_color_mode = "hal_hdr";
+ }
+ } else {
+ hdr_color_mode = "hal_hdr";
+ }
+ DLOGI("Setting color mode = %s", hdr_color_mode.c_str());
+ error = SetColorModeInternal(hdr_color_mode);
+ }
+ comp_manager_->ControlDpps(false); // Disable Dpps
+ }
+ }
+
+ return error;
+}
+
+
+DisplayError DisplayBase::GetClientTargetSupport(uint32_t width, uint32_t height,
+ LayerBufferFormat format,
+ const ColorMetaData &color_metadata) {
+ if (format != kFormatRGBA8888 && format != kFormatRGBA1010102) {
+ DLOGW("Unsupported format = %d", format);
+ return kErrorNotSupported;
+ } else if (ValidateScaling(width, height) != kErrorNone) {
+ DLOGW("Unsupported width = %d height = %d", width, height);
+ return kErrorNotSupported;
+ } else if (color_metadata.transfer && color_metadata.colorPrimaries) {
+ DisplayError error = ValidateDataspace(color_metadata);
+ if (error != kErrorNone) {
+ DLOGW("Unsupported Transfer Request = %d Color Primary = %d",
+ color_metadata.transfer, color_metadata.colorPrimaries);
+ return error;
+ }
+
+ // Check for BT2020 support
+ if (color_metadata.colorPrimaries == ColorPrimaries_BT2020) {
+ DLOGW("Unsupported Color Primary = %d", color_metadata.colorPrimaries);
+ return kErrorNotSupported;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateScaling(uint32_t width, uint32_t height) {
+ uint32_t display_width = display_attributes_.x_pixels;
+ uint32_t display_height = display_attributes_.y_pixels;
+
+ HWResourceInfo hw_resource_info = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+ float max_scale_down = FLOAT(hw_resource_info.max_scale_down);
+ float max_scale_up = FLOAT(hw_resource_info.max_scale_up);
+
+ float scale_x = FLOAT(width / display_width);
+ float scale_y = FLOAT(height / display_height);
+
+ if (scale_x > max_scale_down || scale_y > max_scale_down) {
+ return kErrorNotSupported;
+ }
+
+ if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
+ if ((1.0f / scale_x) > max_scale_up) {
+ return kErrorNotSupported;
+ }
+ }
+
+ if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
+ if ((1.0f / scale_y) > max_scale_up) {
+ return kErrorNotSupported;
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateDataspace(const ColorMetaData &color_metadata) {
+ // Handle transfer
+ switch (color_metadata.transfer) {
+ case Transfer_sRGB:
+ case Transfer_SMPTE_170M:
+ case Transfer_SMPTE_ST2084:
+ case Transfer_HLG:
+ case Transfer_Linear:
+ case Transfer_Gamma2_2:
+ break;
+ default:
+ DLOGW("Unsupported Transfer Request = %d", color_metadata.transfer);
+ return kErrorNotSupported;
+ }
+
+ // Handle colorPrimaries
+ switch (color_metadata.colorPrimaries) {
+ case ColorPrimaries_BT709_5:
+ case ColorPrimaries_BT601_6_525:
+ case ColorPrimaries_BT601_6_625:
+ case ColorPrimaries_DCIP3:
+ case ColorPrimaries_BT2020:
+ break;
+ default:
+ DLOGW("Unsupported Color Primary = %d", color_metadata.colorPrimaries);
+ return kErrorNotSupported;
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sdm