diff options
author | Edward Wang <ewang@cyngn.com> | 2016-06-29 12:41:27 -0700 |
---|---|---|
committer | Edward Wang <ewang@cyngn.com> | 2016-06-29 14:10:41 -0700 |
commit | c005f560bc796e354a07829419a52c9884d9e5e2 (patch) | |
tree | d7713e1f8e50c08422abd918fb5fed38baef01ab | |
parent | 17f2d38f94275d9245f5df2584ad5e3ebc7135e5 (diff) | |
parent | 079eaeba924056fa4dacfa5cb2a12b0ee9c6cfe5 (diff) | |
download | android_hardware_qcom_display-stable/cm-13.0-caf-8996-ZNH2K.tar.gz android_hardware_qcom_display-stable/cm-13.0-caf-8996-ZNH2K.tar.bz2 android_hardware_qcom_display-stable/cm-13.0-caf-8996-ZNH2K.zip |
Merge remote-tracking branch 'remotes/github/staging/LA.HB.1.3.1.c1-05300' into HEADstable/cm-13.0-caf-8996-ZNH2K
Change-Id: Iae4c1f2147aff4b1d6286bc663b0b8fe47bc7b8c
Ticket: CYNGNOS-3131
45 files changed, 764 insertions, 272 deletions
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp index 7411c38e5..430d7fda7 100644 --- a/libgralloc/alloc_controller.cpp +++ b/libgralloc/alloc_controller.cpp @@ -413,6 +413,10 @@ IAllocController* IAllocController::getInstance(void) IonController::IonController() { allocateIonMem(); + + char property[PROPERTY_VALUE_MAX]; + property_get("video.disable.ubwc", property, "0"); + mDisableUBWCForEncode = atoi(property); } void IonController::allocateIonMem() @@ -906,6 +910,11 @@ bool isUBwcEnabled(int format, int usage) if (isUBwcFormat(format)) return true; + if ((usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && + gralloc::IAllocController::getInstance()->isDisableUBWCForEncoder()) { + return false; + } + // Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP // support the format. OR if a non-OpenGL client like Rotator, sets UBWC // usage flag and MDP supports the format. diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h index 919e5724f..8216b0c88 100644 --- a/libgralloc/alloc_controller.h +++ b/libgralloc/alloc_controller.h @@ -56,6 +56,8 @@ class IAllocController { virtual IMemAlloc* getAllocator(int flags) = 0; + virtual bool isDisableUBWCForEncoder(); + virtual ~IAllocController() {}; static IAllocController* getInstance(void); @@ -72,10 +74,15 @@ class IonController : public IAllocController { virtual IMemAlloc* getAllocator(int flags); + virtual bool isDisableUBWCForEncoder() { + return mDisableUBWCForEncode; + } + IonController(); private: IonAlloc* mIonAlloc; + bool mDisableUBWCForEncode; void allocateIonMem(); }; diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp index 203ab9d99..0eee65e53 100644 --- a/libgralloc/gpu.cpp +++ b/libgralloc/gpu.cpp @@ -136,6 +136,11 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage, flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED; } + ColorSpace_t colorSpace = ITU_R_601; + if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) { + colorSpace = ITU_R_601_FR; + } + if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_HW_CAMERA_WRITE | GRALLOC_USAGE_HW_RENDER | @@ -160,7 +165,6 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage, hnd->offset = data.offset; hnd->base = (uint64_t)(data.base) + data.offset; hnd->gpuaddr = 0; - ColorSpace_t colorSpace = ITU_R_601; setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace); *pHandle = hnd; diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp index dcf2ee896..421069f44 100644 --- a/libgralloc/mapper.cpp +++ b/libgralloc/mapper.cpp @@ -484,10 +484,10 @@ int gralloc_perform(struct gralloc_module_t const* module, { private_handle_t* hnd = va_arg(args, private_handle_t*); uint32_t *enable = va_arg(args, uint32_t*); - if (private_handle_t::validate(hnd)) { - return res; + if (!private_handle_t::validate(hnd)) { + setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable); + res = 0; } - setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable); } break; default: break; diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c index 958859ae7..4ad94ce81 100644 --- a/libmemtrack/kgsl.c +++ b/libmemtrack/kgsl.c @@ -85,7 +85,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type, while (1) { unsigned long size; char line_type[7]; - char flags[7]; + char flags[8]; char line_usage[19]; int ret; @@ -95,9 +95,9 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type, /* Format: * gpuaddr useraddr size id flags type usage sglen - * 545ba000 545ba000 4096 1 ----pY gpumem arraybuffer 1 + * 545ba000 545ba000 4096 1 -----pY gpumem arraybuffer 1 */ - ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d\n", + ret = sscanf(line, "%*x %*x %lu %*d %7s %6s %18s %*d\n", &size, flags, line_type, line_usage); if (ret != 4) { continue; @@ -105,7 +105,7 @@ int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type, if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) { - if (flags[5] == 'Y') + if (flags[6] == 'Y') accounted_size += size; else unaccounted_size += size; diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h index 2cf5c80bf..9ba60f2b8 100644 --- a/libqdutils/display_config.h +++ b/libqdutils/display_config.h @@ -47,10 +47,10 @@ namespace qdutils { // Use this enum to specify the dpy parameters where needed enum { - DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY, - DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL, - DISPLAY_TERTIARY = HWC_DISPLAY_TERTIARY, - DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL, + DISPLAY_PRIMARY = 0, + DISPLAY_EXTERNAL, + DISPLAY_TERTIARY, + DISPLAY_VIRTUAL, }; // External Display states - used in setSecondaryDisplayStatus() diff --git a/sdm/include/core/buffer_allocator.h b/sdm/include/core/buffer_allocator.h index 5e8353711..0fd938886 100644 --- a/sdm/include/core/buffer_allocator.h +++ b/sdm/include/core/buffer_allocator.h @@ -108,6 +108,17 @@ class BufferAllocator { */ virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0; + + /*! @brief Method to get the buffer size. + + @details This method returns buffer size for a specific configuration mentioned in buffer info. + + @param[in] buffer_info \link BufferInfo \endlink + + @return \link unsigned int \endlink + */ + virtual uint32_t GetBufferSize(BufferInfo *buffer_info) = 0; + protected: virtual ~BufferAllocator() { } }; diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h index 5d48a04ac..c437dab29 100644 --- a/sdm/include/core/layer_buffer.h +++ b/sdm/include/core/layer_buffer.h @@ -107,6 +107,10 @@ enum LayerBufferFormat { kFormatYCbCr420SPVenusUbwc, //!< UBWC aligned YCbCr420SemiPlanarVenus format + kFormatYCrCb420SemiPlanarVenus, //!< Y-plane: y(0), y(1), y(2) ... y(n) + //!< 2x2 subsampled interleaved UV-plane: + //!< v(0), u(0), v(2), u(2) ... v(n-1), u(n-1) + /* All YUV-Packed formats, Any new format will be added towards end of this group to maintain backward compatibility. */ @@ -118,6 +122,19 @@ enum LayerBufferFormat { kFormatInvalid = 0xFFFFFFFF, }; + +/*! @brief This enum represents different types of 3D formats supported. + + @sa LayerBufferS3DFormat +*/ +enum LayerBufferS3DFormat { + kS3dFormatNone, //!< Layer buffer content is not 3D content. + kS3dFormatLeftRight, //!< Left and Right view of a 3D content stitched left and right. + kS3dFormatRightLeft, //!< Right and Left view of a 3D content stitched left and right. + kS3dFormatTopBottom, //!< Left and RightView of a 3D content stitched top and bottom. + kS3dFormatFramePacking //!< Left and right view of 3D content coded in consecutive frames. +}; + /*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer formats have 1 plane whereas YUV buffer formats may have upto 4 planes. @@ -149,13 +166,12 @@ struct LayerBufferFlags { uint32_t interlace : 1; //!< This flag shall be set by the client to indicate that //!< the buffer has interlaced content. - uint32_t secure_display : 1; - //!< This flag shall be set by the client to indicate that the + uint32_t secure_display : 1; //!< This flag shall be set by the client to indicate that the //!< secure display session is in progress. Secure display //!< session can not coexist with non-secure session. - }; + }; - uint32_t flags = 0; //!< For initialization purpose only. + uint32_t flags = 0; //!< For initialization purpose only. //!< Client shall not refer to it directly. }; }; @@ -198,6 +214,11 @@ struct LayerBuffer { //!< read/write. LayerBufferFlags flags; //!< Flags associated with this buffer. + + LayerBufferS3DFormat s3d_format = kS3dFormatNone; + //!< Represents the format of the buffer content in 3D. + uint64_t buffer_id __attribute__((aligned(8))) = 0; + //!< Specifies the buffer id. }; } // namespace sdm diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h index 9b012026b..34c68fec6 100644 --- a/sdm/include/core/layer_stack.h +++ b/sdm/include/core/layer_stack.h @@ -192,6 +192,10 @@ struct LayerStackFlags { //!< stack contains cursor layer. uint32_t single_buffered_layer_present : 1; //!< Set if stack has single buffered layer + + uint32_t s3d_mode_present : 1; //!< This flag will be set to true, if the current layer + //!< stack contains s3d layer, and the layer stack can enter + //!< s3d mode. }; uint32_t flags = 0; //!< For initialization purpose only. diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h index 2a261ee6c..2b0c3994f 100644 --- a/sdm/include/private/color_params.h +++ b/sdm/include/private/color_params.h @@ -108,6 +108,7 @@ struct PPFeatureVersion { struct PPHWAttributes : HWResourceInfo, HWPanelInfo, DisplayConfigVariableInfo { char panel_name[256] = "generic_panel"; PPFeatureVersion version; + int panel_max_brightness = 0; void Set(const HWResourceInfo &hw_res, const HWPanelInfo &panel_info, const DisplayConfigVariableInfo &attr, const PPFeatureVersion &feature_ver); diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h index 3b668b899..9c8d0890f 100644 --- a/sdm/include/private/hw_info_types.h +++ b/sdm/include/private/hw_info_types.h @@ -28,6 +28,7 @@ #include <stdint.h> #include <core/display_interface.h> #include <core/core_interface.h> +#include <vector> namespace sdm { @@ -66,12 +67,25 @@ enum HWDisplayPort { kPortEDP, }; +enum PipeType { + kPipeTypeUnused, + kPipeTypeVIG, + kPipeTypeRGB, + kPipeTypeDMA, + kPipeTypeCursor, +}; + struct HWDynBwLimitInfo { uint32_t cur_mode = kBwDefault; uint32_t total_bw_limit[kBwModeMax] = { 0 }; uint32_t pipe_bw_limit[kBwModeMax] = { 0 }; }; +struct HWPipeCaps { + PipeType type = kPipeTypeUnused; + uint32_t id = 0; +}; + struct HWResourceInfo { uint32_t hw_version = 0; uint32_t hw_revision = 0; @@ -111,6 +125,7 @@ struct HWResourceInfo { bool perf_calc = false; bool has_dyn_bw_support = false; HWDynBwLimitInfo dyn_bw_info; + std::vector<HWPipeCaps> hw_pipes; void Reset() { *this = HWResourceInfo(); } }; @@ -128,6 +143,15 @@ struct HWSplitInfo { } }; +enum HWS3DMode { + kS3DModeNone, + kS3DModeLR, + kS3DModeRL, + kS3DModeTB, + kS3DModeFP, + kS3DModeMax, +}; + struct HWPanelInfo { HWDisplayPort port = kPortDefault; // Display port HWDisplayMode mode = kModeDefault; // Display mode @@ -143,8 +167,11 @@ struct HWPanelInfo { uint32_t min_fps = 0; // Min fps supported by panel uint32_t max_fps = 0; // Max fps supported by panel bool is_primary_panel = false; // Panel is primary display + bool is_pluggable = false; // Panel is pluggable HWSplitInfo split_info; // Panel split configuration char panel_name[256] = {0}; // Panel name + HWS3DMode s3d_mode = kS3DModeNone; // Panel's current s3d mode. + int panel_max_brightness = 0; // Max panel brightness bool operator !=(const HWPanelInfo &panel_info) { return ((port != panel_info.port) || (mode != panel_info.mode) || @@ -156,7 +183,8 @@ struct HWPanelInfo { (needs_roi_merge != panel_info.needs_roi_merge) || (dynamic_fps != panel_info.dynamic_fps) || (min_fps != panel_info.min_fps) || (max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) || - (split_info != panel_info.split_info)); + (split_info != panel_info.split_info) || + (s3d_mode != panel_info.s3d_mode)); } bool operator ==(const HWPanelInfo &panel_info) { @@ -165,12 +193,8 @@ struct HWPanelInfo { }; struct HWSessionConfig { - uint32_t src_width = 0; - uint32_t src_height = 0; - LayerBufferFormat src_format = kFormatInvalid; - uint32_t dst_width = 0; - uint32_t dst_height = 0; - LayerBufferFormat dst_format = kFormatInvalid; + LayerRect src_rect; + LayerRect dst_rect; uint32_t buffer_count = 0; bool secure = false; bool cache = false; @@ -195,6 +219,7 @@ struct HWRotatorSession { LayerTransform transform; HWSessionConfig hw_session_config; LayerBuffer output_buffer; + LayerBuffer input_buffer; int session_id = -1; float input_compression = 1.0f; float output_compression = 1.0f; @@ -260,6 +285,8 @@ struct HWLayersInfo { uint32_t index[kMaxSDELayers]; // Indexes of the layers from the layer stack which need to be // programmed on hardware. + LayerRect updated_src_rect[kMaxSDELayers]; // Updated layer src rects in s3d mode + LayerRect updated_dst_rect[kMaxSDELayers]; // Updated layer dst rects in s3d mode uint32_t count = 0; // Total number of layers which need to be set on hardware. @@ -286,6 +313,7 @@ struct HWDisplayAttributes : DisplayConfigVariableInfo { uint32_t v_back_porch = 0; //!< Vertical back porch of panel uint32_t v_pulse_width = 0; //!< Vertical pulse width of panel uint32_t h_total = 0; //!< Total width of panel (hActive + hFP + hBP + hPulseWidth) + uint32_t s3d_config = 0; //!< Stores the bit mask of S3D modes void Reset() { *this = HWDisplayAttributes(); } diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h index b4a286a08..251e195cc 100644 --- a/sdm/include/utils/debug.h +++ b/sdm/include/utils/debug.h @@ -64,6 +64,7 @@ class Debug { static int GetSimulationFlag(); static int GetHDMIResolution(); static int GetIdleTimeoutMs(); + static int GetBootAnimLayerCount(); static bool IsRotatorDownScaleDisabled(); static bool IsDecimationDisabled(); static int GetMaxPipesPerMixer(DisplayType display_type); diff --git a/sdm/include/utils/locker.h b/sdm/include/utils/locker.h index bc24ad5de..fffe634a2 100644 --- a/sdm/include/utils/locker.h +++ b/sdm/include/utils/locker.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2016, 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: @@ -89,7 +89,7 @@ class Locker { explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) { locker_.Lock(); - if (locker_.sequence_wait_ == 1) { + while (locker_.sequence_wait_ == 1) { locker_.Wait(); error_ = (locker_.sequence_wait_ == -1); } diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp index 1d224ade6..5dee0628b 100644 --- a/sdm/libs/core/color_manager.cpp +++ b/sdm/libs/core/color_manager.cpp @@ -207,6 +207,7 @@ void PPHWAttributes::Set(const HWResourceInfo &hw_res, DisplayConfigVariableInfo &attributes = *this; attributes = attr; version = feature_ver; + panel_max_brightness = panel_info.panel_max_brightness; if (strlen(panel_info.panel_name)) { snprintf(&panel_name[0], sizeof(panel_name), "%s", &panel_info.panel_name[0]); diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp index c08b41319..41c521333 100644 --- a/sdm/libs/core/comp_manager.cpp +++ b/sdm/libs/core/comp_manager.cpp @@ -418,7 +418,7 @@ bool CompManager::SupportLayerAsCursor(Handle comp_handle, HWLayers *hw_layers) return supported; } - for (int32_t i = layer_stack->layer_count; i >= 0; i--) { + for (int32_t i = layer_stack->layer_count - 1; i >= 0; i--) { Layer &layer = layer_stack->layers[i]; if (layer.composition == kCompositionGPUTarget) { gpu_index = i; diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp index 979e48180..f0b78b3b2 100644 --- a/sdm/libs/core/display_base.cpp +++ b/sdm/libs/core/display_base.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2016, 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: @@ -535,11 +535,6 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { num_modes, active_index); DisplayConfigVariableInfo &info = attrib; - DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%u," - "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi, - info.y_dpi, info.fps, info.vsync_period_ns); - - DumpImpl::AppendString(buffer, length, "\n"); uint32_t num_hw_layers = 0; if (hw_layers_.info.stack) { @@ -551,6 +546,18 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { return; } + LayerBuffer *out_buffer = hw_layers_.info.stack->output_buffer; + if (out_buffer) { + DumpImpl::AppendString(buffer, length, "\nres:%u x %u format: %s", out_buffer->width, + out_buffer->height, GetName(out_buffer->format)); + } else { + DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%u," + "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi, + info.y_dpi, info.fps, info.vsync_period_ns); + } + + DumpImpl::AppendString(buffer, length, "\n"); + HWLayersInfo &layer_info = hw_layers_.info; LayerRect &l_roi = layer_info.left_partial_update; LayerRect &r_roi = layer_info.right_partial_update; @@ -562,9 +569,9 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { INT(r_roi.top), INT(r_roi.right), INT(r_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) |"; //NOLINT - const char *newline = "\n|-----|-------------|--------|----|-------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|"; //NOLINT - const char *format = "\n| %3s | %11s " "| %6s " "| %2s | 0x%03x | %4d x %4d | %24s " "| %4d %4d %4d %4d " "| %4d %4d %4d %4d " "| %2s | %10s " "| %9s |"; //NOLINT + 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 |"; //NOLINT + const char *newline = "\n|-----|-------------|--------|----|-------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|"; //NOLINT + const char *format = "\n| %3s | %11s " "| %6s " "| %2s | 0x%03x | %4d x %4d | %24s " "| %4d %4d %4d %4d " "| %4d %4d %4d %4d " "| %2s | %10s " "| %9s | %2s |"; //NOLINT DumpImpl::AppendString(buffer, length, "\n"); DumpImpl::AppendString(buffer, length, newline); @@ -587,7 +594,7 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { snprintf(idx, sizeof(idx), "%d", layer_index); for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) { - char writeback_id[8]; + char writeback_id[8] = { 0 }; HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count]; LayerRect &src_roi = rotate.src_roi; LayerRect &dst_roi = rotate.dst_roi; @@ -599,7 +606,7 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { 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), "-", "- ", "- "); + INT(dst_roi.bottom), "-", "- ", "- ", "-"); // print the below only once per layer block, fill with spaces for rest. idx[0] = 0; @@ -612,9 +619,11 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { } for (uint32_t count = 0; count < 2; count++) { - char decimation[16]; - char flags[16]; - char z_order[8]; + char decimation[16] = { 0 }; + char flags[16] = { 0 }; + char z_order[8] = { 0 }; + char csc[8] = { 0 }; + HWPipeInfo &pipe = (count == 0) ? layer_config.left_pipe : layer_config.right_pipe; if (!pipe.valid) { @@ -628,13 +637,14 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { snprintf(flags, sizeof(flags), "0x%08x", layer.flags.flags); snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation, pipe.vertical_decimation); + snprintf(csc, sizeof(csc), "%d", layer.csc); DumpImpl::AppendString(buffer, length, 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); + z_order, flags, decimation, csc); // print the below only once per layer block, fill with spaces for rest. idx[0] = 0; @@ -695,6 +705,7 @@ const char * DisplayBase::GetName(const LayerBufferFormat &format) { case kFormatYCbCr420SemiPlanar: return "Y_CBCR_420"; case kFormatYCrCb420SemiPlanar: return "Y_CRCB_420"; case kFormatYCbCr420SemiPlanarVenus: return "Y_CBCR_420_VENUS"; + case kFormatYCrCb420SemiPlanarVenus: return "Y_CRCB_420_VENUS"; case kFormatYCbCr422H1V2SemiPlanar: return "Y_CBCR_422_H1V2"; case kFormatYCrCb422H1V2SemiPlanar: return "Y_CRCB_422_H1V2"; case kFormatYCbCr422H2V1SemiPlanar: return "Y_CBCR_422_H2V1"; diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp index d812f0cfd..123e300fa 100644 --- a/sdm/libs/core/display_hdmi.cpp +++ b/sdm/libs/core/display_hdmi.cpp @@ -24,6 +24,8 @@ #include <utils/constants.h> #include <utils/debug.h> +#include <map> +#include <utility> #include "display_hdmi.h" #include "hw_interface.h" @@ -50,7 +52,14 @@ DisplayError DisplayHDMI::Init() { return error; } - uint32_t active_mode_index = GetBestConfig(); + uint32_t active_mode_index; + char value[64] = "0"; + Debug::GetProperty("sdm.hdmi.s3d_enable", value); + if (atoi(value) != 0) { + active_mode_index = GetBestConfig(kS3DModeLR); + } else { + active_mode_index = GetBestConfig(kS3DModeNone); + } error = hw_intf_->SetDisplayAttributes(active_mode_index); if (error != kErrorNone) { @@ -65,6 +74,16 @@ DisplayError DisplayHDMI::Init() { GetScanSupport(); underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth); + s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode> + (kS3dFormatNone, kS3DModeNone)); + s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode> + (kS3dFormatLeftRight, kS3DModeLR)); + s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode> + (kS3dFormatRightLeft, kS3DModeRL)); + s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode> + (kS3dFormatTopBottom, kS3DModeTB)); + s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode> + (kS3dFormatFramePacking, kS3DModeFP)); return error; } @@ -79,6 +98,9 @@ DisplayError DisplayHDMI::Deinit() { DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) { SCOPE_LOCK(locker_); + + SetS3DMode(layer_stack); + return DisplayBase::Prepare(layer_stack); } @@ -181,39 +203,50 @@ DisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level); } -int DisplayHDMI::GetBestConfig() { - uint32_t best_index = 0; +int DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) { + uint32_t best_index = 0, index; uint32_t num_modes = 0; HWDisplayAttributes best_attrib; hw_intf_->GetNumDisplayAttributes(&num_modes); - if (num_modes == 1) { - return best_index; + + // Get display attribute for each mode + HWDisplayAttributes *attrib = new HWDisplayAttributes[num_modes]; + for (index = 0; index < num_modes; index++) { + hw_intf_->GetDisplayAttributes(index, &attrib[index]); } - hw_intf_->GetDisplayAttributes(0, &best_attrib); - - // From the available configs, select the best - // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60 - for (uint32_t index = 1; index < num_modes; index++) { - HWDisplayAttributes current_attrib; - hw_intf_->GetDisplayAttributes(index, ¤t_attrib); - // compare the two modes: in the order of Resolution followed by refreshrate - if (current_attrib.y_pixels > best_attrib.y_pixels) { - best_index = index; - } else if (current_attrib.y_pixels == best_attrib.y_pixels) { - if (current_attrib.x_pixels > best_attrib.x_pixels) { - best_index = index; - } else if (current_attrib.x_pixels == best_attrib.x_pixels) { - if (current_attrib.vsync_period_ns < best_attrib.vsync_period_ns) { + // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone + for (index = 0; index < num_modes; index ++) { + if (IS_BIT_SET(attrib[index].s3d_config, s3d_mode)) { + break; + } + } + if (index < num_modes) { + best_index = index; + for (size_t index = best_index + 1; index < num_modes; index ++) { + if (!IS_BIT_SET(attrib[index].s3d_config, s3d_mode)) + continue; + + // From the available configs, select the best + // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60 + if (attrib[index].y_pixels > attrib[best_index].y_pixels) { + best_index = index; + } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) { + if (attrib[index].x_pixels > attrib[best_index].x_pixels) { best_index = index; + } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) { + if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) { + best_index = index; + } } } } - if (best_index == index) { - best_attrib = current_attrib; - } + } else { + DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d", + __FUNCTION__, s3d_mode); } + delete[] attrib; // Used for changing HDMI Resolution - override the best with user set config uint32_t user_config = Debug::GetHDMIResolution(); @@ -271,5 +304,55 @@ DisplayError DisplayHDMI::SetCursorPosition(int x, int y) { return DisplayBase::SetCursorPosition(x, y); } +void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) { + uint32_t s3d_layer_count = 0; + HWS3DMode s3d_mode = kS3DModeNone; + HWPanelInfo panel_info; + HWDisplayAttributes display_attributes; + uint32_t active_index = 0; + uint32_t layer_count = layer_stack->layer_count; + + // S3D mode is supported for the following scenarios: + // 1. Layer stack containing only one s3d layer which is not skip + // 2. Layer stack containing only one secure layer along with one s3d layer + for (uint32_t i = 0; i < layer_count; i++) { + Layer &layer = layer_stack->layers[i]; + LayerBuffer *layer_buffer = layer.input_buffer; + + if (layer_buffer->s3d_format != kS3dFormatNone) { + s3d_layer_count++; + if (s3d_layer_count > 1 || layer.flags.skip) { + s3d_mode = kS3DModeNone; + break; + } + + std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it = + s3d_format_to_mode_.find(layer_buffer->s3d_format); + if (it != s3d_format_to_mode_.end()) { + s3d_mode = it->second; + } + } else if (layer_buffer->flags.secure && layer_count > 2) { + s3d_mode = kS3DModeNone; + break; + } + } + + if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) { + hw_intf_->SetS3DMode(kS3DModeNone); + layer_stack->flags.s3d_mode_present = false; + } else if (s3d_mode != kS3DModeNone) { + layer_stack->flags.s3d_mode_present = true; + } + + hw_intf_->GetHWPanelInfo(&panel_info); + hw_intf_->GetActiveConfig(&active_index); + hw_intf_->GetDisplayAttributes(active_index, &display_attributes); + + if (panel_info != hw_panel_info_) { + comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info); + hw_panel_info_ = panel_info; + } +} + } // namespace sdm diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h index ce22104e1..3d2fcc6d4 100644 --- a/sdm/libs/core/display_hdmi.h +++ b/sdm/libs/core/display_hdmi.h @@ -25,6 +25,8 @@ #ifndef __DISPLAY_HDMI_H__ #define __DISPLAY_HDMI_H__ +#include <map> + #include "display_base.h" #include "dump_impl.h" @@ -64,11 +66,13 @@ class DisplayHDMI : public DisplayBase, DumpImpl { virtual DisplayError SetCursorPosition(int x, int y); private: - virtual int GetBestConfig(); + virtual int GetBestConfig(HWS3DMode s3d_mode); virtual void GetScanSupport(); + virtual void SetS3DMode(LayerStack *layer_stack); Locker locker_; HWScanSupport scan_support_; + std::map<LayerBufferS3DFormat, HWS3DMode> s3d_format_to_mode_; }; } // namespace sdm diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp index ea6232512..0309ea693 100644 --- a/sdm/libs/core/fb/hw_device.cpp +++ b/sdm/libs/core/fb/hw_device.cpp @@ -43,6 +43,8 @@ #include <utils/constants.h> #include <utils/debug.h> #include <utils/sys.h> +#include <vector> +#include <algorithm> #include "hw_device.h" #include "hw_info_interface.h" @@ -428,6 +430,10 @@ DisplayError HWDevice::Commit(HWLayers *hw_layers) { // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all // layers being composed by MDP. + + std::vector<uint32_t> fence_dup_flag; + fence_dup_flag.clear(); + for (uint32_t i = 0; i < hw_layer_info.count; i++) { uint32_t layer_index = hw_layer_info.index[i]; LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer; @@ -437,8 +443,14 @@ DisplayError HWDevice::Commit(HWLayers *hw_layers) { input_buffer = &hw_rotator_session->output_buffer; } - input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence); + // Make sure the release fence is duplicated only once for each buffer. + if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), layer_index) == + fence_dup_flag.end()) { + input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence); + fence_dup_flag.push_back(layer_index); + } } + fence_dup_flag.clear(); hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence); @@ -634,7 +646,7 @@ int HWDevice::GetFBNodeIndex(HWDeviceType device_type) { } break; case kDeviceHDMI: - if (panel_info.port == kPortDTv) { + if (panel_info.is_pluggable == true) { return i; } break; @@ -749,6 +761,8 @@ void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) { panel_info->max_fps = atoi(tokens[1]); } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) { panel_info->is_primary_panel = atoi(tokens[1]); + } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) { + panel_info->is_pluggable = atoi(tokens[1]); } } } @@ -756,6 +770,7 @@ void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) { GetHWDisplayPortAndMode(device_node, &panel_info->port, &panel_info->mode); GetSplitInfo(device_node, panel_info); GetHWPanelNameByNode(device_node, panel_info); + GetHWPanelMaxBrightnessFromNode(panel_info); } void HWDevice::GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode) { @@ -838,6 +853,30 @@ void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) { Sys::fclose_(fileptr); } +void HWDevice::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) { + char brightness[kMaxStringLength] = { 0 }; + char kMaxBrightnessNode[64] = { 0 }; + + snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s", + "/sys/class/leds/lcd-backlight/max_brightness"); + + panel_info->panel_max_brightness = 0; + int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY); + if (fd < 0) { + DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode, + strerror(errno)); + return; + } + + if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) { + panel_info->panel_max_brightness = atoi(brightness); + DLOGW("Max brightness level = %d", panel_info->panel_max_brightness); + } else { + DLOGW("Failed to read max brightness level. error = %s", strerror(errno)); + } + Sys::close_(fd); +} + int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) { char *tmp_token = NULL; char *temp_ptr; @@ -1067,5 +1106,9 @@ ssize_t HWDevice::SysFsWrite(const char* file_node, const char* value, ssize_t l return len; } +DisplayError HWDevice::SetS3DMode(HWS3DMode s3d_mode) { + return kErrorNotSupported; +} + } // namespace sdm diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h index 3f6737fe6..a0eeca634 100644 --- a/sdm/libs/core/fb/hw_device.h +++ b/sdm/libs/core/fb/hw_device.h @@ -73,6 +73,7 @@ class HWDevice : public HWInterface { virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level); virtual DisplayError GetPanelBrightness(int *level); virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; } + virtual DisplayError SetS3DMode(HWS3DMode s3d_mode); // For HWDevice derivatives virtual DisplayError Init(HWEventHandler *eventhandler); @@ -103,6 +104,7 @@ class HWDevice : public HWInterface { void GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info); void GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode); void GetSplitInfo(int device_node, HWPanelInfo *panel_info); + void GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info); int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count); int ParseLine(char *input, const char *delim, char *tokens[], const uint32_t max_token, uint32_t *count); diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp index 9c1e7c335..2d91b9d5d 100644 --- a/sdm/libs/core/fb/hw_hdmi.cpp +++ b/sdm/libs/core/fb/hw_hdmi.cpp @@ -36,6 +36,9 @@ #include <linux/videodev2.h> #include <utils/debug.h> #include <utils/sys.h> +#include <vector> +#include <map> +#include <utility> #include "hw_hdmi.h" @@ -142,6 +145,17 @@ DisplayError HWHDMI::Init(HWEventHandler *eventhandler) { ReadScanInfo(); + s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode> + (kS3DModeNone, HDMI_S3D_NONE)); + s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode> + (kS3DModeLR, HDMI_S3D_SIDE_BY_SIDE)); + s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode> + (kS3DModeRL, HDMI_S3D_SIDE_BY_SIDE)); + s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode> + (kS3DModeTB, HDMI_S3D_TOP_AND_BOTTOM)); + s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode> + (kS3DModeFP, HDMI_S3D_FRAME_PACKING)); + return error; } @@ -245,6 +259,8 @@ DisplayError HWHDMI::GetDisplayAttributes(uint32_t index, display_attributes->h_total += h_blanking; } + GetDisplayS3DSupport(index, display_attributes); + return kErrorNone; } @@ -301,6 +317,19 @@ DisplayError HWHDMI::SetDisplayAttributes(uint32_t index) { active_config_index_ = index; + // Get the supported s3d modes for current active config index + HWDisplayAttributes attrib; + GetDisplayS3DSupport(index, &attrib); + supported_s3d_modes_.clear(); + supported_s3d_modes_.push_back(kS3DModeNone); + for (uint32_t mode = kS3DModeNone + 1; mode < kS3DModeMax; mode ++) { + if (IS_BIT_SET(attrib.s3d_config, (HWS3DMode)mode)) { + supported_s3d_modes_.push_back((HWS3DMode)mode); + } + } + + SetS3DMode(kS3DModeNone); + return kErrorNone; } @@ -554,5 +583,116 @@ void HWHDMI::SetSourceProductInformation(const char *node, const char *name) { } } +DisplayError HWHDMI::GetDisplayS3DSupport(uint32_t index, + HWDisplayAttributes *attrib) { + ssize_t length = -1; + char edid_s3d_str[kPageSize] = {'\0'}; + char edid_s3d_path[kMaxStringLength] = {'\0'}; + snprintf(edid_s3d_path, sizeof(edid_s3d_path), "%s%d/edid_3d_modes", fb_path_, fb_node_index_); + + if (index > hdmi_mode_count_) { + return kErrorNotSupported; + } + + SET_BIT(attrib->s3d_config, kS3DModeNone); + + // Three level inception! + // The string looks like 16=SSH,4=FP:TAB:SSH,5=FP:SSH,32=FP:TAB:SSH + char *saveptr_l1, *saveptr_l2, *saveptr_l3; + char *l1, *l2, *l3; + + int edid_s3d_node = Sys::open_(edid_s3d_path, O_RDONLY); + if (edid_s3d_node < 0) { + DLOGW("%s could not be opened : %s", edid_s3d_path, strerror(errno)); + return kErrorNotSupported; + } + + length = Sys::pread_(edid_s3d_node, edid_s3d_str, sizeof(edid_s3d_str)-1, 0); + if (length <= 0) { + Sys::close_(edid_s3d_node); + return kErrorNotSupported; + } + + l1 = strtok_r(edid_s3d_str, ",", &saveptr_l1); + while (l1 != NULL) { + l2 = strtok_r(l1, "=", &saveptr_l2); + if (l2 != NULL) { + if (hdmi_modes_[index] == (uint32_t)atoi(l2)) { + l3 = strtok_r(saveptr_l2, ":", &saveptr_l3); + while (l3 != NULL) { + if (strncmp("SSH", l3, strlen("SSH")) == 0) { + SET_BIT(attrib->s3d_config, kS3DModeLR); + SET_BIT(attrib->s3d_config, kS3DModeRL); + } else if (strncmp("TAB", l3, strlen("TAB")) == 0) { + SET_BIT(attrib->s3d_config, kS3DModeTB); + } else if (strncmp("FP", l3, strlen("FP")) == 0) { + SET_BIT(attrib->s3d_config, kS3DModeFP); + } + l3 = strtok_r(NULL, ":", &saveptr_l3); + } + } + } + l1 = strtok_r(NULL, ",", &saveptr_l1); + } + + Sys::close_(edid_s3d_node); + return kErrorNone; +} + +bool HWHDMI::IsSupportedS3DMode(HWS3DMode s3d_mode) { + for (uint32_t i = 0; i < supported_s3d_modes_.size(); i++) { + if (supported_s3d_modes_[i] == s3d_mode) { + return true; + } + } + return false; +} + +DisplayError HWHDMI::SetS3DMode(HWS3DMode s3d_mode) { + if (!IsSupportedS3DMode(s3d_mode)) { + DLOGW("S3D mode is not supported s3d_mode = %d", s3d_mode); + return kErrorNotSupported; + } + + std::map<HWS3DMode, msm_hdmi_s3d_mode>::iterator it = s3d_mode_sdm_to_mdp_.find(s3d_mode); + if (it == s3d_mode_sdm_to_mdp_.end()) { + return kErrorNotSupported; + } + msm_hdmi_s3d_mode s3d_mdp_mode = it->second; + + if (active_mdp_s3d_mode_ == s3d_mdp_mode) { + // HDMI_S3D_SIDE_BY_SIDE is an mdp mapping for kS3DModeLR and kS3DModeRL s3d modes. So no need + // to update the s3d_mode node. hw_panel_info needs to be updated to differentiate these two s3d + // modes in strategy + hw_panel_info_.s3d_mode = s3d_mode; + return kErrorNone; + } + + ssize_t length = -1; + char s3d_mode_path[kMaxStringLength] = {'\0'}; + char s3d_mode_string[kMaxStringLength] = {'\0'}; + snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_); + + int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR); + if (s3d_mode_node < 0) { + DLOGW("%s could not be opened : %s", s3d_mode_path, strerror(errno)); + return kErrorNotSupported; + } + + snprintf(s3d_mode_string, sizeof(s3d_mode_string), "%d", s3d_mdp_mode); + length = Sys::pwrite_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0); + if (length <= 0) { + DLOGW("Failed to write into s3d node: %s", strerror(errno)); + Sys::close_(s3d_mode_node); + return kErrorNotSupported; + } + + active_mdp_s3d_mode_ = s3d_mdp_mode; + Sys::close_(s3d_mode_node); + + DLOGI_IF(kTagDriverConfig, "s3d mode %d", hw_panel_info_.s3d_mode); + return kErrorNone; +} + } // namespace sdm diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h index 2457ee0c6..09eab2372 100644 --- a/sdm/libs/core/fb/hw_hdmi.h +++ b/sdm/libs/core/fb/hw_hdmi.h @@ -26,6 +26,9 @@ #define __HW_HDMI_H__ #include <video/msm_hdmi_modes.h> +#include <map> +#include <vector> + #include "hw_device.h" namespace sdm { @@ -52,6 +55,7 @@ class HWHDMI : public HWDevice { virtual DisplayError SetDisplayAttributes(uint32_t index); virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index); virtual DisplayError Validate(HWLayers *hw_layers); + virtual DisplayError SetS3DMode(HWS3DMode s3d_mode); private: DisplayError ReadEDIDInfo(); @@ -63,6 +67,9 @@ class HWHDMI : public HWDevice { bool ReadResolutionFile(char *config_buffer); bool IsResolutionFilePresent(); void SetSourceProductInformation(const char *node, const char *name); + DisplayError GetDisplayS3DSupport(uint32_t num_modes, + HWDisplayAttributes *attrib); + bool IsSupportedS3DMode(HWS3DMode s3d_mode); uint32_t hdmi_mode_count_; uint32_t hdmi_modes_[256]; @@ -70,6 +77,9 @@ class HWHDMI : public HWDevice { msm_hdmi_mode_timing_info *supported_video_modes_; HWScanInfo hw_scan_info_; uint32_t active_config_index_; + std::map<HWS3DMode, msm_hdmi_s3d_mode> s3d_mode_sdm_to_mdp_; + std::vector<HWS3DMode> supported_s3d_modes_; + int active_mdp_s3d_mode_ = HDMI_S3D_NONE; }; } // namespace sdm diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp index e163f9a56..1bd8e8c70 100644 --- a/sdm/libs/core/fb/hw_info.cpp +++ b/sdm/libs/core/fb/hw_info.cpp @@ -41,7 +41,7 @@ int HWInfo::ParseLine(char *input, char *tokens[], const uint32_t max_token, uin char *tmp_token = NULL; char *temp_ptr; uint32_t index = 0; - const char *delim = ", =\n"; + const char *delim = ":, =\n"; if (!input) { return -1; } @@ -166,14 +166,6 @@ DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) { if (!ParseLine(line, tokens, max_count, &token_count)) { if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) { hw_resource->hw_revision = UINT32(atoi(tokens[1])); // HW Rev, v1/v2 - } else if (!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) { - hw_resource->num_rgb_pipe = UINT8(atoi(tokens[1])); - } else if (!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) { - hw_resource->num_vig_pipe = UINT8(atoi(tokens[1])); - } else if (!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) { - hw_resource->num_dma_pipe = UINT8(atoi(tokens[1])); - } else if (!strncmp(tokens[0], "cursor_pipes", strlen("cursor_pipes"))) { - hw_resource->num_cursor_pipe = UINT8(atoi(tokens[1])); } else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) { hw_resource->num_blending_stages = UINT8(atoi(tokens[1])); } else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) { @@ -226,6 +218,34 @@ DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) { hw_resource->has_dyn_bw_support = true; } } + } else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) { + uint32_t pipe_count = UINT8(atoi(tokens[1])); + for (uint32_t i = 0; i < pipe_count; i++) { + read = Sys::getline_(&line, &len, fileptr); + if (!ParseLine(line, tokens, max_count, &token_count)) { + HWPipeCaps pipe_caps; + for (uint32_t j = 0; j < token_count; j += 2) { + if (!strncmp(tokens[j], "pipe_type", strlen("pipe_type"))) { + if (!strncmp(tokens[j+1], "vig", strlen("vig"))) { + pipe_caps.type = kPipeTypeVIG; + hw_resource->num_vig_pipe++; + } else if (!strncmp(tokens[j+1], "rgb", strlen("rgb"))) { + pipe_caps.type = kPipeTypeRGB; + hw_resource->num_rgb_pipe++; + } else if (!strncmp(tokens[j+1], "dma", strlen("dma"))) { + pipe_caps.type = kPipeTypeDMA; + hw_resource->num_dma_pipe++; + } else if (!strncmp(tokens[j+1], "cursor", strlen("cursor"))) { + pipe_caps.type = kPipeTypeCursor; + hw_resource->num_cursor_pipe++; + } + } else if (!strncmp(tokens[j], "pipe_ndx", strlen("pipe_ndx"))) { + pipe_caps.id = UINT32(atoi(tokens[j+1])); + } + } + hw_resource->hw_pipes.push_back(pipe_caps); + } + } } } } diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp index 9a2c897cf..93d1f42e3 100644 --- a/sdm/libs/core/fb/hw_primary.cpp +++ b/sdm/libs/core/fb/hw_primary.cpp @@ -669,10 +669,16 @@ DisplayError HWPrimary::SetAutoRefresh(bool enable) { char buffer[kWriteLength] = {'\0'}; ssize_t bytes = snprintf(buffer, kWriteLength, "%d", enable); + if (enable == auto_refresh_) { + return kErrorNone; + } + if (HWDevice::SysFsWrite(kAutoRefreshNode, buffer, bytes) <= 0) { // Returns bytes written return kErrorUndefined; } + auto_refresh_ = enable; + return kErrorNone; } diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h index 629171e55..9e2cea351 100644 --- a/sdm/libs/core/fb/hw_primary.h +++ b/sdm/libs/core/fb/hw_primary.h @@ -96,6 +96,7 @@ class HWPrimary : public HWDevice { uint32_t active_config_index_ = 0; const char *kBrightnessNode = "/sys/class/leds/lcd-backlight/brightness"; const char *kAutoRefreshNode = "/sys/devices/virtual/graphics/fb0/msm_cmd_autorefresh_en"; + bool auto_refresh_ = false; }; } // namespace sdm diff --git a/sdm/libs/core/fb/hw_virtual.cpp b/sdm/libs/core/fb/hw_virtual.cpp index 27c979ae4..033159f44 100644 --- a/sdm/libs/core/fb/hw_virtual.cpp +++ b/sdm/libs/core/fb/hw_virtual.cpp @@ -74,9 +74,5 @@ DisplayError HWVirtual::Validate(HWLayers *hw_layers) { return HWDevice::Validate(hw_layers); } -DisplayError HWVirtual::Flush() { - return kErrorNone; -} - } // namespace sdm diff --git a/sdm/libs/core/fb/hw_virtual.h b/sdm/libs/core/fb/hw_virtual.h index c0591b310..2b740d565 100644 --- a/sdm/libs/core/fb/hw_virtual.h +++ b/sdm/libs/core/fb/hw_virtual.h @@ -39,7 +39,6 @@ class HWVirtual : public HWDevice { HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf); virtual DisplayError Init(HWEventHandler *eventhandler); virtual DisplayError Validate(HWLayers *hw_layers); - virtual DisplayError Flush(); }; } // namespace sdm diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h index c9c73b9c7..9e9114f24 100644 --- a/sdm/libs/core/hw_interface.h +++ b/sdm/libs/core/hw_interface.h @@ -91,6 +91,7 @@ class HWInterface { virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) = 0; virtual DisplayError GetPanelBrightness(int *level) = 0; virtual DisplayError SetAutoRefresh(bool enable) = 0; + virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0; protected: virtual ~HWInterface() { } diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp index ca73c36c6..46582b8d6 100644 --- a/sdm/libs/core/resource_default.cpp +++ b/sdm/libs/core/resource_default.cpp @@ -36,38 +36,40 @@ namespace sdm { DisplayError ResourceDefault::Init(const HWResourceInfo &hw_res_info) { DisplayError error = kErrorNone; - uint32_t num_pipe = 0; - num_pipe = hw_res_info.num_vig_pipe + hw_res_info.num_rgb_pipe + hw_res_info.num_dma_pipe; + num_pipe_ = hw_res_info.num_vig_pipe + hw_res_info.num_rgb_pipe + hw_res_info.num_dma_pipe; - if (num_pipe > kPipeIdMax) { - DLOGE("Number of pipe is over the limit! %d", num_pipe); + if (!num_pipe_) { + DLOGE("Number of H/W pipes is Zero!"); return kErrorParameters; } - num_pipe_ = num_pipe; + src_pipes_ = new SourcePipe[num_pipe_]; hw_res_info_ = hw_res_info; - // Init pipe info - vig_pipes_ = &src_pipes_[0]; - rgb_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe]; - dma_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe]; - - for (uint32_t i = 0; i < hw_res_info_.num_vig_pipe; i++) { - vig_pipes_[i].type = kPipeTypeVIG; - vig_pipes_[i].index = i; - vig_pipes_[i].mdss_pipe_id = GetMdssPipeId(vig_pipes_[i].type, i); - } - for (uint32_t i = 0; i < hw_res_info_.num_rgb_pipe; i++) { - rgb_pipes_[i].type = kPipeTypeRGB; - rgb_pipes_[i].index = i + hw_res_info_.num_vig_pipe; - rgb_pipes_[i].mdss_pipe_id = GetMdssPipeId(rgb_pipes_[i].type, i); - } + // Priority order of pipes: VIG, RGB, DMA + uint32_t vig_index = 0; + uint32_t rgb_index = hw_res_info_.num_vig_pipe; + uint32_t dma_index = rgb_index + hw_res_info_.num_rgb_pipe; - for (uint32_t i = 0; i < hw_res_info_.num_dma_pipe; i++) { - dma_pipes_[i].type = kPipeTypeDMA; - dma_pipes_[i].index = i + hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe; - dma_pipes_[i].mdss_pipe_id = GetMdssPipeId(dma_pipes_[i].type, i); + for (uint32_t i = 0; i < num_pipe_; i++) { + const HWPipeCaps &pipe_caps = hw_res_info_.hw_pipes.at(i); + if (pipe_caps.type == kPipeTypeVIG) { + src_pipes_[vig_index].type = kPipeTypeVIG; + src_pipes_[vig_index].index = i; + src_pipes_[vig_index].mdss_pipe_id = pipe_caps.id; + vig_index++; + } else if (pipe_caps.type == kPipeTypeRGB) { + src_pipes_[rgb_index].type = kPipeTypeRGB; + src_pipes_[rgb_index].index = i; + src_pipes_[rgb_index].mdss_pipe_id = pipe_caps.id; + rgb_index++; + } else if (pipe_caps.type == kPipeTypeDMA) { + src_pipes_[dma_index].type = kPipeTypeDMA; + src_pipes_[dma_index].index = i; + src_pipes_[dma_index].mdss_pipe_id = pipe_caps.id; + dma_index++; + } } for (uint32_t i = 0; i < num_pipe_; i++) { @@ -86,14 +88,16 @@ DisplayError ResourceDefault::Init(const HWResourceInfo &hw_res_info) { // TODO(user): clean it up, query from driver for initial pipe status. #ifndef SDM_VIRTUAL_DRIVER - rgb_pipes_[0].owner = kPipeOwnerKernelMode; - rgb_pipes_[1].owner = kPipeOwnerKernelMode; + rgb_index = hw_res_info_.num_vig_pipe; + src_pipes_[rgb_index].owner = kPipeOwnerKernelMode; + src_pipes_[rgb_index + 1].owner = kPipeOwnerKernelMode; #endif return error; } DisplayError ResourceDefault::Deinit() { + delete[] src_pipes_; return kErrorNone; } @@ -212,8 +216,8 @@ DisplayError ResourceDefault::Acquire(Handle display_ctx, HWLayers *hw_layers) { } } - uint32_t left_index = kPipeIdMax; - uint32_t right_index = kPipeIdMax; + uint32_t left_index = num_pipe_; + uint32_t right_index = num_pipe_; bool need_scale = false; struct HWLayerConfig &layer_config = hw_layers->config[0]; @@ -332,45 +336,9 @@ DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max return kErrorNone; } -uint32_t ResourceDefault::GetMdssPipeId(PipeType type, uint32_t index) { - uint32_t mdss_id = kPipeIdMax; - switch (type) { - case kPipeTypeVIG: - if (index < 3) { - mdss_id = kPipeIdVIG0 + index; - } else if (index == 3) { - mdss_id = kPipeIdVIG3; - } else { - DLOGE("vig pipe index is over the limit! %d", index); - } - break; - case kPipeTypeRGB: - if (index < 3) { - mdss_id = kPipeIdRGB0 + index; - } else if (index == 3) { - mdss_id = kPipeIdRGB3; - } else { - DLOGE("rgb pipe index is over the limit! %d", index); - } - break; - case kPipeTypeDMA: - if (index < 2) { - mdss_id = kPipeIdDMA0 + index; - } else { - DLOGE("dma pipe index is over the limit! %d", index); - } - break; - default: - DLOGE("wrong pipe type! %d", type); - break; - } - - return (1 << mdss_id); -} - uint32_t ResourceDefault::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes, uint32_t num_pipe) { - uint32_t index = kPipeIdMax; + uint32_t index = num_pipe_; SourcePipe *src_pipe; // search the pipe being used @@ -392,16 +360,16 @@ uint32_t ResourceDefault::NextPipe(PipeType type, HWBlockType hw_block_id) { switch (type) { case kPipeTypeVIG: - src_pipes = vig_pipes_; + src_pipes = &src_pipes_[0]; num_pipe = hw_res_info_.num_vig_pipe; break; case kPipeTypeRGB: - src_pipes = rgb_pipes_; + src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe]; num_pipe = hw_res_info_.num_rgb_pipe; break; case kPipeTypeDMA: default: - src_pipes = dma_pipes_; + src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe]; num_pipe = hw_res_info_.num_dma_pipe; break; } @@ -410,7 +378,7 @@ uint32_t ResourceDefault::NextPipe(PipeType type, HWBlockType hw_block_id) { } uint32_t ResourceDefault::GetPipe(HWBlockType hw_block_id, bool need_scale) { - uint32_t index = kPipeIdMax; + uint32_t index = num_pipe_; // The default behavior is to assume RGB and VG pipes have scalars if (!need_scale) { diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h index 67bb0fd3c..1dc51ad79 100644 --- a/sdm/libs/core/resource_default.h +++ b/sdm/libs/core/resource_default.h @@ -56,28 +56,6 @@ class ResourceDefault : public ResourceInterface { DisplayError SetMaxBandwidthMode(HWBwModes mode); private: - enum PipeId { - kPipeIdVIG0, - kPipeIdVIG1, - kPipeIdVIG2, - kPipeIdRGB0, - kPipeIdRGB1, - kPipeIdRGB2, - kPipeIdDMA0, - kPipeIdDMA1, - kPipeIdVIG3, - kPipeIdRGB3, - kPipeIdMax, - }; - - enum PipeType { - kPipeTypeUnused, - kPipeTypeVIG, - kPipeTypeRGB, - kPipeTypeDMA, - kPipeTypeMax, - }; - enum PipeOwner { kPipeOwnerUserMode, // Pipe state when it is available for reservation kPipeOwnerKernelMode, // Pipe state when pipe is owned by kernel @@ -96,7 +74,7 @@ class ResourceDefault : public ResourceInterface { HWBlockType hw_block_id; int priority; - SourcePipe() : type(kPipeTypeUnused), owner(kPipeOwnerUserMode), mdss_pipe_id(kPipeIdMax), + SourcePipe() : type(kPipeTypeUnused), owner(kPipeOwnerUserMode), mdss_pipe_id(0), index(0), hw_block_id(kHWBlockMax), priority(0) { } inline void ResetState() { hw_block_id = kHWBlockMax;} @@ -115,7 +93,6 @@ class ResourceDefault : public ResourceInterface { HWBlockContext() : is_in_use(false) { } }; - uint32_t GetMdssPipeId(PipeType pipe_type, uint32_t index); uint32_t NextPipe(PipeType pipe_type, HWBlockType hw_block_id); uint32_t SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes, uint32_t num_pipe); uint32_t GetPipe(HWBlockType hw_block_id, bool need_scale); @@ -146,11 +123,8 @@ class ResourceDefault : public ResourceInterface { Locker locker_; HWResourceInfo hw_res_info_; HWBlockContext hw_block_ctx_[kHWBlockMax]; - SourcePipe src_pipes_[kPipeIdMax]; + SourcePipe *src_pipes_ = NULL; uint32_t num_pipe_ = 0; - SourcePipe *vig_pipes_ = NULL; - SourcePipe *rgb_pipes_ = NULL; - SourcePipe *dma_pipes_ = NULL; }; } // namespace sdm diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp index 0b7bd3cdf..582fda7d3 100644 --- a/sdm/libs/core/strategy.cpp +++ b/sdm/libs/core/strategy.cpp @@ -138,6 +138,8 @@ DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) { for (uint32_t i = 0; i < layer_stack->layer_count; i++) { LayerComposition &composition = layer_stack->layers[i].composition; if (composition == kCompositionGPUTarget) { + hw_layers_info_->updated_src_rect[hw_layer_count] = layer_stack->layers[i].src_rect; + hw_layers_info_->updated_dst_rect[hw_layer_count] = layer_stack->layers[i].dst_rect; hw_layers_info_->index[hw_layer_count++] = i; } else if (composition != kCompositionBlitTarget) { composition = kCompositionGPU; diff --git a/sdm/libs/hwc/Android.mk b/sdm/libs/hwc/Android.mk index 93b5acc64..ead0034fb 100644 --- a/sdm/libs/hwc/Android.mk +++ b/sdm/libs/hwc/Android.mk @@ -13,7 +13,7 @@ LOCAL_C_INCLUDES := $(call project-path-for,qcom-display)/sdm/inclu LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \ -Wall -Werror -std=c++11 -fcolor-diagnostics\ - -DLOG_TAG=\"SDM\" + -DLOG_TAG=\"SDM\" -DDEBUG_CALC_FPS LOCAL_CLANG := true # TODO: Move this to the common makefile @@ -21,6 +21,12 @@ ifeq ($(call is-board-platform-in-list, msm8996),true) LOCAL_CFLAGS += -DMASTER_SIDE_CP endif + +ifeq ($(TARGET_USES_QCOM_BSP),true) +# Enable QCOM Display features +LOCAL_CFLAGS += -DQTI_BSP +endif + LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \ libutils libcutils libsync libmemalloc libqdutils libdl \ libpowermanager libsdmutils libc++ diff --git a/sdm/libs/hwc/blit_engine_c2d.cpp b/sdm/libs/hwc/blit_engine_c2d.cpp index be8c6f962..a7f621d54 100644 --- a/sdm/libs/hwc/blit_engine_c2d.cpp +++ b/sdm/libs/hwc/blit_engine_c2d.cpp @@ -57,6 +57,7 @@ #include <utils/rect.h> #include "blit_engine_c2d.h" +#include "hwc_debugger.h" #define __CLASS__ "BlitEngineC2D" @@ -88,11 +89,13 @@ int BlitEngineC2d::RegionIterator::iterate(copybit_region_t const *self, copybit return 0; } -BlitEngineC2d::BlitEngineC2d() : blit_active_(false), dump_frame_count_(0), dump_frame_index_(0) { +BlitEngineC2d::BlitEngineC2d() { for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) { blit_target_buffer_[i] = NULL; release_fence_fd_[i] = -1; } + + HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_supported_); } BlitEngineC2d::~BlitEngineC2d() { @@ -250,8 +253,7 @@ int BlitEngineC2d::Prepare(LayerStack *layer_stack) { for (i = 0; i < layer_stack->layer_count; i++) { Layer &layer = layer_stack->layers[i]; - if (IsUBWCFormat(layer.input_buffer->format)) { - // UBWC is not currently supported + if (!blit_supported_) { return -1; } if (layer.composition == kCompositionGPUTarget) { diff --git a/sdm/libs/hwc/blit_engine_c2d.h b/sdm/libs/hwc/blit_engine_c2d.h index 74c4b813e..5400611b9 100644 --- a/sdm/libs/hwc/blit_engine_c2d.h +++ b/sdm/libs/hwc/blit_engine_c2d.h @@ -112,9 +112,10 @@ class BlitEngineC2d : public BlitEngine { int release_fence_fd_[kNumBlitTargetBuffers]; uint32_t num_blit_target_; int blit_target_start_index_; - bool blit_active_; - uint32_t dump_frame_count_; - uint32_t dump_frame_index_; + bool blit_active_ = false; + uint32_t dump_frame_count_ = 0; + uint32_t dump_frame_index_ = 0; + int blit_supported_ = 0; }; } // namespace sdm diff --git a/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm/libs/hwc/hwc_buffer_allocator.cpp index 314971847..10c719bde 100644 --- a/sdm/libs/hwc/hwc_buffer_allocator.cpp +++ b/sdm/libs/hwc/hwc_buffer_allocator.cpp @@ -150,6 +150,42 @@ DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) { return kErrorNone; } +uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) { + uint32_t align = getpagesize(); + + const BufferConfig &buffer_config = buffer_info->buffer_config; + + int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP); + + int width = INT(buffer_config.width); + int height = INT(buffer_config.height); + int format; + + if (buffer_config.secure) { + alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP); + alloc_flags |= INT(GRALLOC_USAGE_PROTECTED); + align = SECURE_ALIGN; + } + + if (buffer_config.cache == false) { + // Allocate uncached buffers + alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED; + } + + if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) { + return 0; + } + + int aligned_width = 0; + int aligned_height = 0; + uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags, + aligned_width, aligned_height); + + buffer_size = ROUND_UP(buffer_size, align) * buffer_config.buffer_count; + + return buffer_size; +} + int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int *flags) { switch (format) { case kFormatRGBA8888: *target = HAL_PIXEL_FORMAT_RGBA_8888; break; @@ -164,6 +200,7 @@ int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int case kFormatYCbCr422H2V1Packed: *target = HAL_PIXEL_FORMAT_YCbCr_422_I; break; case kFormatYCbCr422H2V1SemiPlanar: *target = HAL_PIXEL_FORMAT_YCbCr_422_SP; break; case kFormatYCbCr420SemiPlanarVenus: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; break; + case kFormatYCrCb420SemiPlanarVenus: *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS; break; case kFormatYCbCr420SPVenusUbwc: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC; break; case kFormatRGBA5551: *target = HAL_PIXEL_FORMAT_RGBA_5551; break; case kFormatRGBA4444: *target = HAL_PIXEL_FORMAT_RGBA_4444; break; diff --git a/sdm/libs/hwc/hwc_buffer_allocator.h b/sdm/libs/hwc/hwc_buffer_allocator.h index b3f8add63..e576fe81e 100644 --- a/sdm/libs/hwc/hwc_buffer_allocator.h +++ b/sdm/libs/hwc/hwc_buffer_allocator.h @@ -48,6 +48,7 @@ class HWCBufferAllocator : public BufferAllocator { DisplayError AllocateBuffer(BufferInfo *buffer_info); DisplayError FreeBuffer(BufferInfo *buffer_info); + uint32_t GetBufferSize(BufferInfo *buffer_info); private: struct MetaBufferInfo { diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp index a3b8a9084..ebb5c7b28 100644 --- a/sdm/libs/hwc/hwc_display.cpp +++ b/sdm/libs/hwc/hwc_display.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2016, 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 @@ -36,17 +36,19 @@ #include <utils/debug.h> #include <sync/sync.h> #include <cutils/properties.h> +#include <map> +#include <utility> #include "hwc_display.h" #include "hwc_debugger.h" #include "blit_engine_c2d.h" -#define __CLASS__ "HWCDisplay" - -#if 0 -#include <exhwcomposer_defs.h> +#ifdef QTI_BSP +#include <hardware/display_defs.h> #endif +#define __CLASS__ "HWCDisplay" + namespace sdm { static void AssignLayerRegionsAddress(LayerRectArray *region, uint32_t rect_count, @@ -112,6 +114,14 @@ int HWCDisplay::Init() { display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_); current_refresh_rate_ = max_refresh_rate_; + s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_NO_3D, kS3dFormatNone)); + s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_L_R, + kS3dFormatLeftRight)); + s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_R_L, + kS3dFormatRightLeft)); + s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_TOP_BOTTOM, + kS3dFormatTopBottom)); + return 0; } @@ -245,11 +255,6 @@ int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *attributes case HWC_DISPLAY_DPI_Y: values[i] = INT32(variable_config.y_dpi * 1000.0f); break; -#if 0 - case HWC_DISPLAY_SECURE: - values[i] = INT32(true); // For backward compatibility. All Physical displays are secure - break; -#endif default: DLOGW("Spurious attribute type = %d", attributes[i]); return -EINVAL; @@ -567,10 +572,9 @@ int HWCDisplay::PrePrepareLayerStack(hwc_display_contents_1_t *content_list) { layer.flags.updating = true; if (num_hw_layers <= kMaxLayerCount) { - LayerCache layer_cache = layer_stack_cache_.layer_cache[i]; - layer.flags.updating = IsLayerUpdating(hwc_layer, layer_cache); + layer.flags.updating = IsLayerUpdating(content_list, i); } -#if 0 +#ifdef QTI_BSP if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) { layer_stack_.flags.animating = true; } @@ -588,6 +592,8 @@ int HWCDisplay::PrePrepareLayerStack(hwc_display_contents_1_t *content_list) { } else { layer.frame_rate = current_refresh_rate_; } + + layer.input_buffer->buffer_id = reinterpret_cast<uint64_t>(hwc_layer.handle); } // Prepare the Blit Target @@ -794,8 +800,15 @@ int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) { bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) { uint32_t layer_count = layer_stack_.layer_count; + // Handle ongoing animation and end here, start is handled below if (layer_stack_cache_.animating) { - return false; + if (!layer_stack_.flags.animating) { + // Animation is ending. + return true; + } else { + // Animation is going on. + return false; + } } // Frame buffer needs to be refreshed for the following reasons: @@ -808,10 +821,14 @@ bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) } for (uint32_t i = 0; i < layer_count; i++) { - hwc_layer_1_t &hwc_layer = content_list->hwLayers[i]; Layer &layer = layer_stack_.layers[i]; LayerCache &layer_cache = layer_stack_cache_.layer_cache[i]; + // need FB refresh for s3d case + if (layer.input_buffer->s3d_format != kS3dFormatNone) { + return true; + } + if (layer.composition == kCompositionGPUTarget) { continue; } @@ -820,7 +837,7 @@ bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) return true; } - if ((layer.composition == kCompositionGPU) && IsLayerUpdating(hwc_layer, layer_cache)) { + if ((layer.composition == kCompositionGPU) && IsLayerUpdating(content_list, i)) { return true; } } @@ -828,22 +845,30 @@ bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) return false; } -bool HWCDisplay::IsLayerUpdating(const hwc_layer_1_t &hwc_layer, const LayerCache &layer_cache) { +bool HWCDisplay::IsLayerUpdating(hwc_display_contents_1_t *content_list, int layer_index) { + hwc_layer_1_t &hwc_layer = content_list->hwLayers[layer_index]; + LayerCache &layer_cache = layer_stack_cache_.layer_cache[layer_index]; + const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle); const MetaData_t *meta_data = pvt_handle ? reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata) : NULL; - // If a layer is in single buffer mode, it should be considered as updating always + // Layer should be considered updating if + // a) layer is in single buffer mode, or + // b) layer handle has changed, or + // c) layer plane alpha has changed, or + // d) layer stack geometry has changed return ((meta_data && (meta_data->operation & SET_SINGLE_BUFFER_MODE) && - meta_data->isSingleBufferMode) || + meta_data->isSingleBufferMode) || (layer_cache.handle != hwc_layer.handle) || - (layer_cache.plane_alpha != hwc_layer.planeAlpha)); + (layer_cache.plane_alpha != hwc_layer.planeAlpha) || + (content_list->flags & HWC_GEOMETRY_CHANGED)); } void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) { uint32_t layer_count = layer_stack_.layer_count; - if (layer_count > kMaxLayerCount) { + if (layer_count > kMaxLayerCount || layer_stack_.flags.animating) { ResetLayerCacheStack(); return; } @@ -955,6 +980,7 @@ LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flag case HAL_PIXEL_FORMAT_BGR_565: format = kFormatBGR565; break; case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: format = kFormatYCbCr420SemiPlanarVenus; break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: format = kFormatYCrCb420SemiPlanarVenus; break; case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: format = kFormatYCbCr420SPVenusUbwc; break; case HAL_PIXEL_FORMAT_YV12: format = kFormatYCrCb420PlanarStride16; break; case HAL_PIXEL_FORMAT_YCrCb_420_SP: format = kFormatYCrCb420SemiPlanar; break; @@ -1067,6 +1093,8 @@ const char *HWCDisplay::GetHALPixelFormatString(int format) { return "INTERLACE"; case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: return "YCbCr_420_SP_VENUS"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: + return "YCrCb_420_SP_VENUS"; case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: return "YCbCr_420_SP_VENUS_UBWC"; default: @@ -1194,6 +1222,7 @@ void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) { int HWCDisplay::SetDisplayStatus(uint32_t display_status) { int status = 0; + const hwc_procs_t *hwc_procs = *hwc_procs_; switch (display_status) { case kDisplayStatusResume: @@ -1211,6 +1240,11 @@ int HWCDisplay::SetDisplayStatus(uint32_t display_status) { return -EINVAL; } + if (display_status == kDisplayStatusResume || + display_status == kDisplayStatusPause) { + hwc_procs->invalidate(hwc_procs); + } + return status; } @@ -1251,15 +1285,6 @@ void HWCDisplay::MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list) } } -void HWCDisplay::CloseAcquireFences(hwc_display_contents_1_t *content_list) { - for (size_t i = 0; i < content_list->numHwLayers; i++) { - if (content_list->hwLayers[i].acquireFenceFd >= 0) { - close(content_list->hwLayers[i].acquireFenceFd); - content_list->hwLayers[i].acquireFenceFd = -1; - } - } -} - uint32_t HWCDisplay::RoundToStandardFPS(uint32_t fps) { static const uint32_t standard_fps[4] = {30, 24, 48, 60}; @@ -1350,6 +1375,16 @@ DisplayError HWCDisplay::SetMetaData(const private_handle_t *pvt_handle, Layer * layer_stack_.flags.single_buffered_layer_present |= meta_data->isSingleBufferMode; } + if (meta_data->operation & S3D_FORMAT) { + std::map<int, LayerBufferS3DFormat>::iterator it = + s3d_format_hwc_to_sdm_.find(meta_data->s3dFormat); + if (it != s3d_format_hwc_to_sdm_.end()) { + layer->input_buffer->s3d_format = it->second; + } else { + DLOGW("Invalid S3D format %d", meta_data->s3dFormat); + } + } + return kErrorNone; } @@ -1368,7 +1403,9 @@ int HWCDisplay::GetPanelBrightness(int *level) { } int HWCDisplay::ToggleScreenUpdates(bool enable) { + const hwc_procs_t *hwc_procs = *hwc_procs_; display_paused_ = enable ? false : true; + hwc_procs->invalidate(hwc_procs); return 0; } diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h index 53d9c40e7..abf7ec62c 100644 --- a/sdm/libs/hwc/hwc_display.h +++ b/sdm/libs/hwc/hwc_display.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2016, 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: @@ -29,6 +29,7 @@ #include <core/core_interface.h> #include <qdMetaData.h> #include <private/color_params.h> +#include <map> namespace sdm { @@ -141,7 +142,6 @@ class HWCDisplay : public DisplayEventHandler { const char *GetDisplayString(); void ScaleDisplayFrame(hwc_rect_t *display_frame); void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list); - void CloseAcquireFences(hwc_display_contents_1_t *content_list); uint32_t RoundToStandardFPS(uint32_t fps); virtual void ApplyScanAdjustment(hwc_rect_t *display_frame); DisplayError SetCSC(ColorSpace_t source, LayerCSC *target); @@ -149,7 +149,7 @@ class HWCDisplay : public DisplayEventHandler { DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer); bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list); void CacheLayerStackInfo(hwc_display_contents_1_t *content_list); - bool IsLayerUpdating(const hwc_layer_1_t &hwc_layer, const LayerCache &layer_cache); + bool IsLayerUpdating(hwc_display_contents_1_t *content_list, int layer_index); bool SingleLayerUpdating(uint32_t app_layer_count); uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate); @@ -190,6 +190,7 @@ class HWCDisplay : public DisplayEventHandler { bool solid_fill_enable_ = false; uint32_t solid_fill_color_ = 0; LayerRect display_rect_; + std::map<int, LayerBufferS3DFormat> s3d_format_hwc_to_sdm_; private: bool IsFrameBufferScaled(); diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp index 28582f128..74a79bbce 100755..100644 --- a/sdm/libs/hwc/hwc_display_external.cpp +++ b/sdm/libs/hwc/hwc_display_external.cpp @@ -97,6 +97,11 @@ int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) { return status; } + if (content_list->numHwLayers <= 1) { + flush_ = true; + return 0; + } + status = PrepareLayerStack(content_list); if (status) { return status; @@ -109,7 +114,6 @@ int HWCDisplayExternal::Commit(hwc_display_contents_1_t *content_list) { int status = 0; if (secure_display_active_) { - CloseAcquireFences(content_list); return status; } @@ -151,13 +155,16 @@ void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) { return; } + uint32_t new_panel_width = panel_width * (1.0f - width_ratio); + uint32_t new_panel_height = panel_height * (1.0f - height_ratio); + int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f); int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f); - display_frame->left = display_frame->left + x_offset; - display_frame->top = display_frame->top + y_offset; - display_frame->right = display_frame->right - x_offset; - display_frame->bottom = display_frame->bottom - y_offset; + display_frame->left = ((display_frame->left * new_panel_width) / panel_width) + x_offset; + display_frame->top = ((display_frame->top * new_panel_height) / panel_height) + y_offset; + display_frame->right = ((display_frame->right * new_panel_width) / panel_width) + x_offset; + display_frame->bottom = ((display_frame->bottom * new_panel_height) / panel_height) + y_offset; } void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active) { diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp index fb134a971..cd08d689e 100755..100644 --- a/sdm/libs/hwc/hwc_display_primary.cpp +++ b/sdm/libs/hwc/hwc_display_primary.cpp @@ -97,15 +97,37 @@ int HWCDisplayPrimary::Init() { return HWCDisplay::Init(); } -void HWCDisplayPrimary::ProcessBootAnimCompleted() { - char value[PROPERTY_VALUE_MAX]; +void HWCDisplayPrimary::ProcessBootAnimCompleted(hwc_display_contents_1_t *list) { + uint32_t numBootUpLayers = 0; - // Applying default mode after bootanimation is finished - property_get("init.svc.bootanim", value, "running"); - if (!strncmp(value, "stopped", strlen("stopped"))) { - boot_animation_completed_ = true; + numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount()); - // one-shot action check if bootanimation completed then apply default display mode. + if (numBootUpLayers == 0) { + numBootUpLayers = 2; + } + /* All other checks namely "init.svc.bootanim" or + * HWC_GEOMETRY_CHANGED fail in correctly identifying the + * exact bootup transition to homescreen + */ + char cryptoState[PROPERTY_VALUE_MAX]; + char voldDecryptState[PROPERTY_VALUE_MAX]; + bool isEncrypted = false; + bool main_class_services_started = false; + if (property_get("ro.crypto.state", cryptoState, "unencrypted")) { + DLOGI("%s: cryptostate= %s", __FUNCTION__, cryptoState); + if (!strcmp(cryptoState, "encrypted")) { + isEncrypted = true; + if (property_get("vold.decrypt", voldDecryptState, "") && + !strcmp(voldDecryptState, "trigger_restart_framework")) + main_class_services_started = true; + DLOGI("%s: vold= %s", __FUNCTION__, voldDecryptState); + } + } + if ((!isEncrypted ||(isEncrypted && main_class_services_started)) && + (list->numHwLayers > numBootUpLayers)) { + boot_animation_completed_ = true; + // Applying default mode after bootanimation is finished And + // If Data is Encrypted, it is ready for access. if (display_intf_) display_intf_->ApplyDefaultDisplayMode(); } @@ -113,9 +135,10 @@ void HWCDisplayPrimary::ProcessBootAnimCompleted() { int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) { int status = 0; + DisplayError error = kErrorNone; if (!boot_animation_completed_) - ProcessBootAnimCompleted(); + ProcessBootAnimCompleted(content_list); if (display_paused_) { MarkLayersForGPUBypass(content_list); @@ -136,7 +159,10 @@ int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) { ToggleCPUHint(one_updating_layer); uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer); - DisplayError error = display_intf_->SetRefreshRate(refresh_rate); + if (current_refresh_rate_ != refresh_rate) { + error = display_intf_->SetRefreshRate(refresh_rate); + } + if (error == kErrorNone) { // On success, set current refresh rate to new refresh rate current_refresh_rate_ = refresh_rate; @@ -146,6 +172,11 @@ int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) { handle_idle_timeout_ = false; } + if (content_list->numHwLayers <= 1) { + flush_ = true; + return 0; + } + status = PrepareLayerStack(content_list); if (status) { return status; @@ -164,7 +195,6 @@ int HWCDisplayPrimary::Commit(hwc_display_contents_1_t *content_list) { close(content_list->outbufAcquireFenceFd); content_list->outbufAcquireFenceFd = -1; } - CloseAcquireFences(content_list); DisplayError error = display_intf_->Flush(); if (error != kErrorNone) { diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h index e30d20049..377371792 100644 --- a/sdm/libs/hwc/hwc_display_primary.h +++ b/sdm/libs/hwc/hwc_display_primary.h @@ -55,7 +55,7 @@ class HWCDisplayPrimary : public HWCDisplay { HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs); void SetMetaDataRefreshRateFlag(bool enable); virtual DisplayError SetDisplayMode(uint32_t mode); - void ProcessBootAnimCompleted(); + void ProcessBootAnimCompleted(hwc_display_contents_1_t *content_list); void SetQDCMSolidFillInfo(bool enable, uint32_t color); void ToggleCPUHint(bool set); void ForceRefreshRate(uint32_t refresh_rate); diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp index 4d8c24ec8..f216f89ee 100644 --- a/sdm/libs/hwc/hwc_display_virtual.cpp +++ b/sdm/libs/hwc/hwc_display_virtual.cpp @@ -163,15 +163,6 @@ int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) { int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) { int status = 0; if (display_paused_) { - if (content_list->outbufAcquireFenceFd >= 0) { - // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd, - // which will make sure the framework waits on it and closes it. - content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd); - close(content_list->outbufAcquireFenceFd); - content_list->outbufAcquireFenceFd = -1; - } - CloseAcquireFences(content_list); - DisplayError error = display_intf_->Flush(); if (error != kErrorNone) { DLOGE("Flush failed. Error = %d", error); @@ -191,11 +182,6 @@ int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) { return status; } - if (content_list->outbufAcquireFenceFd >= 0) { - close(content_list->outbufAcquireFenceFd); - content_list->outbufAcquireFenceFd = -1; - } - return 0; } diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp index 779b44035..c84fab1d0 100644 --- a/sdm/libs/hwc/hwc_session.cpp +++ b/sdm/libs/hwc/hwc_session.cpp @@ -43,6 +43,7 @@ #include <display_config.h> #include <utils/debug.h> #include <sync/sync.h> +#include <profiler.h> #include "hwc_buffer_allocator.h" #include "hwc_buffer_sync_handler.h" @@ -302,14 +303,26 @@ int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays, } if (hotplug_connect) { + // notify client hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true); - hwc_procs->invalidate(hwc_procs); } - // Return 0, else client will go into bad state return 0; } +int HWCSession::GetVsyncPeriod(int disp) { + SCOPE_LOCK(locker_); + // default value + int32_t vsync_period = 1000000000l / 60; + const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD; + + if (hwc_display_[disp]) { + hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period); + } + + return vsync_period; +} + int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays, hwc_display_contents_1_t **displays) { DTRACE_SCOPED(); @@ -337,32 +350,18 @@ int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays, // Drop virtual display composition if virtual display object could not be created // due to HDMI concurrency. if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) { - if (!content_list) { - continue; + CloseAcquireFds(content_list); + if (content_list) { + content_list->retireFenceFd = -1; } - for (size_t i = 0; i < content_list->numHwLayers; i++) { - int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd; - if (acquireFenceFd >= 0) { - close(acquireFenceFd); - acquireFenceFd = -1; - } - } - - int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd; - if (outbufAcquireFenceFd >= 0) { - close(outbufAcquireFenceFd); - outbufAcquireFenceFd = -1; - } - - content_list->retireFenceFd = -1; - continue; } if (hwc_session->hwc_display_[dpy]) { hwc_session->hwc_display_[dpy]->Commit(content_list); } + CloseAcquireFds(content_list); } if (hwc_session->new_bw_mode_) { @@ -374,10 +373,32 @@ int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays, hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd); } + // This is only indicative of how many times SurfaceFlinger posts + // frames to the display. + CALC_FPS(); + // Return 0, else client will go into bad state return 0; } +void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) { + if (content_list) { + for (size_t i = 0; i < content_list->numHwLayers; i++) { + int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd; + if (acquireFenceFd >= 0) { + close(acquireFenceFd); + acquireFenceFd = -1; + } + } + + int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd; + if (outbufAcquireFenceFd >= 0) { + close(outbufAcquireFenceFd); + outbufAcquireFenceFd = -1; + } + } +} + int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) { SEQUENCE_WAIT_SCOPE_LOCK(locker_); @@ -1090,6 +1111,9 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel return -1; } + pending_action.action = kNoAction; + pending_action.params = NULL; + // Read display_id, payload_size and payload from in_parcel. ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload); if (!ret) { @@ -1308,14 +1332,18 @@ int HWCSession::HotPlugHandler(bool connected) { external_pending_connect_ = false; } } - - // notify client and trigger a screen refresh + if (connected && notify_hotplug) { + // trigger screen refresh to ensure sufficient resources are available to process new + // new display connection. + hwc_procs_->invalidate(hwc_procs_); + int32_t vsync_period = GetVsyncPeriod(HWC_DISPLAY_PRIMARY); + usleep(vsync_period * 2 / 1000); + } + // notify client if (notify_hotplug) { hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected); } - hwc_procs_->invalidate(hwc_procs_); - return 0; } diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h index 455ea831d..561de3574 100644 --- a/sdm/libs/hwc/hwc_session.h +++ b/sdm/libs/hwc/hwc_session.h @@ -73,6 +73,7 @@ class HWCSession : hwc_composer_device_1_t, public qClient::BnQClient { static int GetActiveConfig(hwc_composer_device_1 *device, int disp); static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index); static int SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y); + static void CloseAcquireFds(hwc_display_contents_1_t *content_list); // Uevent thread static void* HWCUeventThread(void *context); @@ -83,6 +84,7 @@ class HWCSession : hwc_composer_device_1_t, public qClient::BnQClient { int ConnectDisplay(int disp, hwc_display_contents_1_t *content_list); int DisconnectDisplay(int disp); void HandleSecureDisplaySession(hwc_display_contents_1_t **displays); + int GetVsyncPeriod(int disp); // QClient methods virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel, diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp index 003be5a21..d0d21ee95 100644 --- a/sdm/libs/utils/debug.cpp +++ b/sdm/libs/utils/debug.cpp @@ -59,6 +59,13 @@ int Debug::GetIdleTimeoutMs() { return value; } +int Debug::GetBootAnimLayerCount() { + int value = 0; + debug_.debug_handler_->GetProperty("sdm.boot_anim_layer_count", &value); + + return value; +} + bool Debug::IsRotatorDownScaleDisabled() { int value = 0; debug_.debug_handler_->GetProperty("sdm.debug.rotator_downscale", &value); |