diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h index 71767e7b..6e3b0053 100644 --- a/libdrmutils/drm_interface.h +++ b/libdrmutils/drm_interface.h @@ -124,6 +124,12 @@ enum struct DRMOps { * uint64_t - Address of the scaler config object (version based) */ PLANE_SET_SCALER_CONFIG, + /* + * Op: Sets plane rotation destination rect + * Arg: uint32_t - Plane ID + * DRMRect - rotator dst Rectangle + */ + PLANE_SET_ROTATION_DST_RECT, /* * Op: Activate or deactivate a CRTC * Arg: uint32_t - CRTC ID @@ -315,6 +321,7 @@ struct DRMPlaneTypeInfo { uint32_t max_horizontal_deci; uint32_t max_vertical_deci; uint64_t max_pipe_bandwidth; + uint32_t cache_size; // cache size in bytes for inline rotation support. }; // All DRM Planes as map listed from highest to lowest priority diff --git a/sdm/include/core/sdm_types.h b/sdm/include/core/sdm_types.h index fae11531..ce356bfa 100644 --- a/sdm/include/core/sdm_types.h +++ b/sdm/include/core/sdm_types.h @@ -55,6 +55,7 @@ enum DisplayError { kErrorShutDown, //!< Driver is processing shutdown sequence kErrorPerfValidation, //!< Bandwidth or Clock requirement validation failure. kErrorNoAppLayers, //!< No App layer(s) in the draw cycle. + kErrorRotatorValidation, //!< Rotator configuration validation failure. }; /*! @brief This structure is defined for client and library compatibility check purpose only. This diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h index cdfec2ed..64e84548 100644 --- a/sdm/include/private/hw_info_types.h +++ b/sdm/include/private/hw_info_types.h @@ -205,6 +205,7 @@ struct HWResourceInfo { uint32_t undersized_prefill_lines = 0; CompRatioMap comp_ratio_rt_map; CompRatioMap comp_ratio_nrt_map; + uint32_t cache_size = 0; // cache size in bytes void Reset() { *this = HWResourceInfo(); } }; @@ -321,6 +322,12 @@ struct HWSessionConfig { } }; +enum HWRotatorMode { + kRotatorNone, + kRotatorOffline, + kRotatorInline +}; + struct HWRotateInfo { int pipe_id = -1; // Not actual pipe id, but the relative DMA id int writeback_id = -1; // Writeback block id, but this is the same as DMA id @@ -342,6 +349,7 @@ struct HWRotatorSession { float input_compression = 1.0f; float output_compression = 1.0f; bool is_buffer_cached = false; + HWRotatorMode mode = kRotatorNone; }; struct HWScaleLutInfo { diff --git a/sdm/include/utils/formats.h b/sdm/include/utils/formats.h index dd819dcd..2d438506 100644 --- a/sdm/include/utils/formats.h +++ b/sdm/include/utils/formats.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2016 - 2017, 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 @@ -34,10 +34,28 @@ namespace sdm { +struct FormatTileSize { + /*< Tile width in pixels. For YUV formats this will give only the + tile width for Y plane*/ + uint32_t tile_width = 0; + /*< Tile height in pixels. For YUV formats this will give only the + tile height for Y plane*/ + uint32_t tile_height = 0; + + /*< Tile width in pixels. Only valid for YUV formats where this will + give tile width for UV plane*/ + uint32_t uv_tile_width = 0; + /*< Tile height in pixels. Only valid for YUV formats where this will + give tile height for UV plane*/ + uint32_t uv_tile_height = 0; +}; + bool IsUBWCFormat(LayerBufferFormat format); bool Is10BitFormat(LayerBufferFormat format); const char *GetFormatString(const LayerBufferFormat &format); BufferLayout GetBufferLayout(LayerBufferFormat format); +DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size); +float GetBufferFormatBpp(LayerBufferFormat format); } // namespace sdm diff --git a/sdm/include/utils/rect.h b/sdm/include/utils/rect.h index ea6edfb1..303fc9f1 100644 --- a/sdm/include/utils/rect.h +++ b/sdm/include/utils/rect.h @@ -60,6 +60,11 @@ namespace sdm { void TransformHV(const LayerRect &src_domain, const LayerRect &in_rect, const LayerTransform &transform, LayerRect *out_rect); RectOrientation GetOrientation(const LayerRect &in_rect); + DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst, + bool rotate90, float *crop_width, float *crop_height, + float *dst_width, float *dst_height); + DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, bool rotate90, + float *scale_x, float *scale_y); } // namespace sdm #endif // __RECT_H__ diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp index 618dd2e2..f6540cd1 100644 --- a/sdm/libs/core/display_base.cpp +++ b/sdm/libs/core/display_base.cpp @@ -590,21 +590,24 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { char idx[8] = { 0 }; const char *comp_type = GetName(sdm_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 writeback_id[8] = { "I" }; HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count]; LayerRect &src_roi = rotate.src_roi; LayerRect &dst_roi = rotate.dst_roi; + const char *rotate_split[2] = { "Rot-1", "Rot-2" }; + int pipe_id = 0; - snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id); - + if (hw_rotator_session.mode == kRotatorOffline) { + snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id); + pipe_id = rotate.pipe_id; + } DumpImpl::AppendString(buffer, length, format, idx, comp_type, rotate_split[count], - writeback_id, rotate.pipe_id, input_buffer->width, + writeback_id, 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), @@ -633,8 +636,11 @@ void DisplayBase::AppendDump(char *buffer, uint32_t length) { continue; } - LayerRect &src_roi = pipe.src_roi; + LayerRect src_roi = pipe.src_roi; LayerRect &dst_roi = pipe.dst_roi; + if (hw_rotator_session.mode == kRotatorInline) { + src_roi = hw_rotator_session.hw_rotate_info[count].dst_roi; + } snprintf(z_order, sizeof(z_order), "%d", pipe.z_order); snprintf(flags, sizeof(flags), "0x%08x", hw_layer.flags.flags); diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp index 10286630..76df517f 100644 --- a/sdm/libs/core/drm/hw_device_drm.cpp +++ b/sdm/libs/core/drm/hw_device_drm.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -225,7 +226,7 @@ void HWDeviceDRM::Registry::RegisterCurrent(HWLayers *hw_layers) { HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session; HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[0]; - if (hw_rotate_info->valid) { + if (hw_rotator_session->mode == kRotatorOffline && hw_rotate_info->valid) { input_buffer = &hw_rotator_session->output_buffer; } @@ -652,15 +653,13 @@ void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) { HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe; HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe; HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session; - bool needs_rotation = false; for (uint32_t count = 0; count < 2; count++) { HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe; HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count]; - if (hw_rotate_info->valid) { + if (hw_rotator_session->mode == kRotatorOffline && hw_rotate_info->valid) { input_buffer = &hw_rotator_session->output_buffer; - needs_rotation = true; } uint32_t fb_id = registry_.GetFbId(input_buffer->planes[0].fd); @@ -674,21 +673,17 @@ void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) { DRMRect src = {}; SetRect(pipe_info->src_roi, &src); drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src); + DRMRect rot_dst = {0, 0, 0, 0}; + if (hw_rotator_session->mode == kRotatorInline && hw_rotate_info->valid) { + SetRect(hw_rotate_info->dst_roi, &rot_dst); + drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION_DST_RECT, pipe_id, rot_dst); + } DRMRect dst = {}; SetRect(pipe_info->dst_roi, &dst); drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst); uint32_t rot_bit_mask = 0; - // In case of rotation, rotator handles flips - if (!needs_rotation) { - if (layer.transform.flip_horizontal) { - rot_bit_mask |= UINT32(DRMRotation::FLIP_H); - } - if (layer.transform.flip_vertical) { - rot_bit_mask |= UINT32(DRMRotation::FLIP_V); - } - } - + SetRotation(layer.transform, hw_rotator_session->mode, &rot_bit_mask); drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask); drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id, pipe_info->horizontal_decimation); @@ -828,7 +823,7 @@ DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) { for (uint32_t i = 0; i < hw_layer_info.hw_layers.size(); i++) { Layer &layer = hw_layer_info.hw_layers.at(i); HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session; - if (hw_rotator_session->hw_block_count) { + if (hw_rotator_session->mode == kRotatorOffline) { hw_rotator_session->output_buffer.release_fence_fd = Sys::dup_(release_fence); } else { layer.input_buffer.release_fence_fd = Sys::dup_(release_fence); @@ -874,6 +869,36 @@ void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) { target->bottom = UINT32(source.bottom); } +void HWDeviceDRM::SetRotation(LayerTransform transform, const HWRotatorMode &mode, + uint32_t* rot_bit_mask) { + // In offline rotation case, rotator will handle flips set via offline rotator interface. + if (mode == kRotatorOffline) { + *rot_bit_mask = 0; + return; + } + + // In no rotation case or inline rotation case, plane will handle flips + // In DRM framework rotation is applied in counter-clockwise direction. + if (transform.rotation == 90) { + // a) rotate 90 clockwise = rotate 270 counter-clockwise in DRM + // rotate 270 is translated as hflip + vflip + rotate90 + // b) rotate 270 clockwise = rotate 90 counter-clockwise in DRM + // c) hflip + rotate 90 clockwise = vflip + rotate 90 counter-clockwise in DRM + // d) vflip + rotate 90 clockwise = hflip + rotate 90 counter-clockwise in DRM + *rot_bit_mask = UINT32(DRMRotation::ROT_90); + transform.flip_horizontal = !transform.flip_horizontal; + transform.flip_vertical = !transform.flip_vertical; + } + + if (transform.flip_horizontal) { + *rot_bit_mask |= UINT32(DRMRotation::FLIP_H); + } + + if (transform.flip_vertical) { + *rot_bit_mask |= UINT32(DRMRotation::FLIP_V); + } +} + bool HWDeviceDRM::EnableHotPlugDetection(int enable) { return true; } diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h index ad7a3e37..84f15d46 100644 --- a/sdm/libs/core/drm/hw_device_drm.h +++ b/sdm/libs/core/drm/hw_device_drm.h @@ -119,6 +119,7 @@ class HWDeviceDRM : public HWInterface { void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target); void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config); void SetRect(const LayerRect &source, sde_drm::DRMRect *target); + void SetRotation(LayerTransform transform, const HWRotatorMode &mode, uint32_t* rot_bit_mask); DisplayError DefaultCommit(HWLayers *hw_layers); DisplayError AtomicCommit(HWLayers *hw_layers); void SetupAtomic(HWLayers *hw_layers, bool validate); diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp index 6258d736..d5bd5cf1 100644 --- a/sdm/libs/core/drm/hw_info_drm.cpp +++ b/sdm/libs/core/drm/hw_info_drm.cpp @@ -332,6 +332,7 @@ void HWInfoDRM::PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info, hw_resource->max_scale_up = info.max_upscale; hw_resource->has_decimation = info.max_horizontal_deci > 1 && info.max_vertical_deci > 1; hw_resource->max_pipe_bw = info.max_pipe_bandwidth / kKiloUnit; + hw_resource->cache_size = info.cache_size; } void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type, diff --git a/sdm/libs/utils/formats.cpp b/sdm/libs/utils/formats.cpp index b7deb183..4b7190ba 100644 --- a/sdm/libs/utils/formats.cpp +++ b/sdm/libs/utils/formats.cpp @@ -127,5 +127,87 @@ BufferLayout GetBufferLayout(LayerBufferFormat format) { } } +float GetBufferFormatBpp(LayerBufferFormat format) { + float bpp = 0.0f; + switch (format) { + case kFormatARGB8888: + case kFormatRGBA8888: + case kFormatBGRA8888: + case kFormatXRGB8888: + case kFormatRGBX8888: + case kFormatBGRX8888: + case kFormatRGBA8888Ubwc: + case kFormatRGBX8888Ubwc: + case kFormatRGBA1010102: + case kFormatARGB2101010: + case kFormatRGBX1010102: + case kFormatXRGB2101010: + case kFormatBGRA1010102: + case kFormatABGR2101010: + case kFormatBGRX1010102: + case kFormatXBGR2101010: + case kFormatRGBA1010102Ubwc: + case kFormatRGBX1010102Ubwc: + return 4.0f; + case kFormatRGB888: + case kFormatBGR888: + case kFormatYCbCr420P010: + case kFormatYCbCr420P010Ubwc: + return 3.0f; + case kFormatRGB565: + case kFormatBGR565: + case kFormatRGBA5551: + case kFormatRGBA4444: + case kFormatBGR565Ubwc: + case kFormatYCbCr422H2V1Packed: + case kFormatCbYCrY422H2V1Packed: + case kFormatYCrCb422H2V1SemiPlanar: + case kFormatYCbCr422H2V1SemiPlanar: + case kFormatYCbCr420TP10Ubwc: + case kFormatYCbCr422H1V2SemiPlanar: + case kFormatYCrCb422H1V2SemiPlanar: + return 2.0f; + case kFormatYCbCr420Planar: + case kFormatYCrCb420Planar: + case kFormatYCrCb420PlanarStride16: + case kFormatYCbCr420SemiPlanar: + case kFormatYCrCb420SemiPlanar: + case kFormatYCbCr420SemiPlanarVenus: + case kFormatYCrCb420SemiPlanarVenus: + case kFormatYCbCr420SPVenusUbwc: + return 1.5f; + default: + return 0.0f; + } + + return bpp; +} + +DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size) { + switch (format) { + case kFormatYCbCr420SPVenusUbwc: + tile_size->tile_width = 32; + tile_size->tile_height = 8; + tile_size->uv_tile_width = 16; + tile_size->uv_tile_height = 8; + break; + case kFormatYCbCr420TP10Ubwc: + tile_size->tile_width = 48; + tile_size->tile_height = 4; + tile_size->uv_tile_width = 24; + tile_size->uv_tile_height = 4; + break; + case kFormatYCbCr420P010Ubwc: + tile_size->tile_width = 32; + tile_size->tile_height = 4; + tile_size->uv_tile_width = 16; + tile_size->uv_tile_height = 4; + break; + default: + return kErrorNotSupported; + } + return kErrorNone; +} + } // namespace sdm diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp index b0cd536e..c227cb30 100644 --- a/sdm/libs/utils/rect.cpp +++ b/sdm/libs/utils/rect.cpp @@ -261,5 +261,47 @@ RectOrientation GetOrientation(const LayerRect &in_rect) { return kOrientationLandscape; } +DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst, + const bool rotated90, float *crop_width, + float *crop_height, float *dst_width, + float *dst_height) { + if (!IsValid(crop)) { + Log(kTagResources, "Invalid crop rect", crop); + return kErrorNotSupported; + } + + if (!IsValid(dst)) { + Log(kTagResources, "Invalid dst rect", dst); + return kErrorNotSupported; + } + + *crop_width = crop.right - crop.left; + *crop_height = crop.bottom - crop.top; + if (rotated90) { + std::swap(*crop_width, *crop_height); + } + + *dst_width = dst.right - dst.left; + *dst_height = dst.bottom - dst.top; + + return kErrorNone; +} + +DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, + bool rotated90, float *scale_x, float *scale_y) { + float crop_width = 1.0f, crop_height = 1.0f, dst_width = 1.0f, dst_height = 1.0f; + + DisplayError error = GetCropAndDestination(crop, dst, rotated90, &crop_width, &crop_height, + &dst_width, &dst_height); + if (error != kErrorNone) { + return error; + } + + *scale_x = crop_width / dst_width; + *scale_y = crop_height / dst_height; + + return kErrorNone; +} + } // namespace sdm