diff options
author | Naseer Ahmed <naseer@codeaurora.org> | 2016-03-12 02:03:48 -0500 |
---|---|---|
committer | Naseer Ahmed <naseer@codeaurora.org> | 2016-04-28 17:42:00 -0400 |
commit | b92e73fc10b5fefa69ef93031a91412527d56971 (patch) | |
tree | 50cec063f21015e63dbbf5d502e43ba253059c2c /sdm/libs/hwc2/hwc_layers.cpp | |
parent | c14b2088b079c637cea23dd97d2f68fd7ed624b8 (diff) | |
download | display-b92e73fc10b5fefa69ef93031a91412527d56971.tar.gz |
hwc: HWC 2.0 implementation
Add HWCLayer, HWCCallbacks and implement HWC2 layer functionality.
Change-Id: Ic7764e72f4cae534e68764df4cf80eb3db982071
Diffstat (limited to 'sdm/libs/hwc2/hwc_layers.cpp')
-rw-r--r-- | sdm/libs/hwc2/hwc_layers.cpp | 500 |
1 files changed, 500 insertions, 0 deletions
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp new file mode 100644 index 00000000..9be23178 --- /dev/null +++ b/sdm/libs/hwc2/hwc_layers.cpp @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hwc_layers.h" +#include <gr.h> +#include <utils/debug.h> +#include <cmath> + +#define __CLASS__ "HWCLayer" + +namespace sdm { + +bool SortLayersByZ::operator()(const HWCLayer *lhs, const HWCLayer *rhs) { + return lhs->GetZ() < rhs->GetZ(); +} + +std::atomic<hwc2_layer_t> HWCLayer::next_id_(1); + +// Layer operations +HWCLayer::HWCLayer(hwc2_display_t display_id) : id_(next_id_++), display_id_(display_id) { + layer_ = new Layer(); + layer_->input_buffer = new LayerBuffer(); + // Fences are deferred, so the first time this layer is presented, return -1 + // TODO(user): Verify that fences are properly obtained on suspend/resume + release_fences_.push(-1); +} + +HWCLayer::~HWCLayer() { + // Close any fences left for this layer + while (!release_fences_.empty()) { + close(release_fences_.front()); + release_fences_.pop(); + } + + if (layer_) { + if (layer_->input_buffer) { + delete (layer_->input_buffer); + } + delete layer_; + } +} + +HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) { + if (!buffer) { + DLOGE("Invalid buffer handle: %p on layer: %d", buffer, id_); + return HWC2::Error::BadParameter; + } + + const private_handle_t *handle = static_cast<const private_handle_t *>(buffer); + LayerBuffer *layer_buffer = layer_->input_buffer; + layer_buffer->width = UINT32(handle->width); + layer_buffer->height = UINT32(handle->height); + layer_buffer->format = GetSDMFormat(handle->format, handle->flags); + if (SetMetaData(handle, layer_) != kErrorNone) { + return HWC2::Error::BadLayer; + } + + if (handle->bufferType == BUFFER_TYPE_VIDEO) { + layer_buffer->flags.video = true; + } + // TZ Protected Buffer - L1 + if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { + layer_buffer->flags.secure = true; + } + if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) { + layer_buffer->flags.secure_display = true; + } + + layer_buffer->planes[0].fd = handle->fd; + layer_buffer->planes[0].offset = handle->offset; + layer_buffer->planes[0].stride = UINT32(handle->width); + layer_buffer->acquire_fence_fd = acquire_fence; + layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle); + + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) { + auto num_dirty_rects = damage.numRects; + if (num_dirty_rects > 0) { + for (uint32_t i = 0; i <= damage.numRects; i++) { + LayerRect rect; + SetRect(damage.rects[i], &rect); + layer_->dirty_regions.push_back(rect); + } + } + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerBlendMode(HWC2::BlendMode mode) { + switch (mode) { + case HWC2::BlendMode::Coverage: + layer_->blending = kBlendingCoverage; + break; + case HWC2::BlendMode::Premultiplied: + layer_->blending = kBlendingPremultiplied; + break; + case HWC2::BlendMode::None: + layer_->blending = kBlendingOpaque; + break; + default: + return HWC2::Error::BadParameter; + } + geometry_changes_ |= kBlendMode; + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerColor(hwc_color_t color) { + layer_->solid_fill_color = GetUint32Color(color); + layer_->input_buffer->format = kFormatARGB8888; + DLOGD("Layer color set to: %u", layer_->solid_fill_color); + DLOGD("[%" PRIu64 "][%" PRIu64 "] Layer color set to %u %" PRIu64, display_id_, id_, + layer_->solid_fill_color); + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerCompositionType(HWC2::Composition type) { + layer_->flags = {}; // Reset earlier flags + composition_ = type; // Used to compute changes + switch (type) { + case HWC2::Composition::Client: + layer_->flags.skip = true; + break; + case HWC2::Composition::Device: + // We try and default to this in SDM + break; + case HWC2::Composition::SolidColor: + layer_->flags.solid_fill = true; + break; + case HWC2::Composition::Cursor: + layer_->flags.cursor = true; + break; + case HWC2::Composition::Invalid: + return HWC2::Error::BadParameter; + default: + return HWC2::Error::Unsupported; + } + // TODO(user): Check if this should be set here or somewhere else + layer_->flags.updating = true; + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerDataspace(int32_t dataspace) { + // TODO(user): Implement later + geometry_changes_ |= kDataspace; + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerDisplayFrame(hwc_rect_t frame) { + SetRect(frame, &layer_->dst_rect); + geometry_changes_ |= kDisplayFrame; + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) { + // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter + layer_->plane_alpha = static_cast<uint8_t>(255.0f * alpha + 0.5f); + geometry_changes_ |= kPlaneAlpha; + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerSourceCrop(hwc_frect_t crop) { + SetRect(crop, &layer_->src_rect); + geometry_changes_ |= kSourceCrop; + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerTransform(HWC2::Transform transform) { + switch (transform) { + case HWC2::Transform::FlipH: + layer_->transform.flip_horizontal = true; + break; + case HWC2::Transform::FlipV: + layer_->transform.flip_vertical = true; + break; + case HWC2::Transform::Rotate90: + layer_->transform.rotation = 90.0f; + break; + case HWC2::Transform::Rotate180: + layer_->transform.rotation = 180.0f; + break; + case HWC2::Transform::Rotate270: + layer_->transform.rotation = 270.0f; + break; + case HWC2::Transform::FlipHRotate90: + layer_->transform.rotation = 90.0f; + layer_->transform.flip_horizontal = true; + break; + case HWC2::Transform::FlipVRotate90: + layer_->transform.rotation = 90.0f; + layer_->transform.flip_vertical = true; + break; + default: + layer_->transform.rotation = 0.0f; + layer_->transform.flip_horizontal = false; + layer_->transform.flip_vertical = false; + } + geometry_changes_ |= kTransform; + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerVisibleRegion(hwc_region_t visible) { + auto num_dirty_rects = visible.numRects; + if (num_dirty_rects > 0) { + for (uint32_t i = 0; i <= visible.numRects; i++) { + LayerRect rect; + SetRect(visible.rects[i], &rect); + layer_->visible_regions.push_back(rect); + } + } + + return HWC2::Error::None; +} + +HWC2::Error HWCLayer::SetLayerZOrder(uint32_t z) { + z_ = z; + geometry_changes_ |= kZOrder; + return HWC2::Error::None; +} + +void HWCLayer::SetRect(const hwc_rect_t &source, LayerRect *target) { + target->left = FLOAT(source.left); + target->top = FLOAT(source.top); + target->right = FLOAT(source.right); + target->bottom = FLOAT(source.bottom); +} + +void HWCLayer::SetRect(const hwc_frect_t &source, LayerRect *target) { + // Recommended way of rounding as in hwcomposer2.h - SetLayerSourceCrop + target->left = std::ceil(source.left); + target->top = std::ceil(source.top); + target->right = std::floor(source.right); + target->bottom = std::floor(source.bottom); +} + +uint32_t HWCLayer::GetUint32Color(const hwc_color_t &source) { + // Returns 32 bit ARGB + uint32_t a = UINT32(source.a) << 24; + uint32_t r = UINT32(source.r) << 16; + uint32_t g = UINT32(source.g) << 8; + uint32_t b = UINT32(source.b); + uint32_t color = a & r & g & b; + return color; +} + +LayerBufferFormat HWCLayer::GetSDMFormat(const int32_t &source, const int flags) { + LayerBufferFormat format = kFormatInvalid; + if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { + switch (source) { + case HAL_PIXEL_FORMAT_RGBA_8888: + format = kFormatRGBA8888Ubwc; + break; + case HAL_PIXEL_FORMAT_RGBX_8888: + format = kFormatRGBX8888Ubwc; + break; + case HAL_PIXEL_FORMAT_BGR_565: + format = kFormatBGR565Ubwc; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: + format = kFormatYCbCr420SPVenusUbwc; + break; + default: + DLOGE("Unsupported format type for UBWC %d", source); + return kFormatInvalid; + } + return format; + } + + switch (source) { + case HAL_PIXEL_FORMAT_RGBA_8888: + format = kFormatRGBA8888; + break; + case HAL_PIXEL_FORMAT_RGBA_5551: + format = kFormatRGBA5551; + break; + case HAL_PIXEL_FORMAT_RGBA_4444: + format = kFormatRGBA4444; + break; + case HAL_PIXEL_FORMAT_BGRA_8888: + format = kFormatBGRA8888; + break; + case HAL_PIXEL_FORMAT_RGBX_8888: + format = kFormatRGBX8888; + break; + case HAL_PIXEL_FORMAT_BGRX_8888: + format = kFormatBGRX8888; + break; + case HAL_PIXEL_FORMAT_RGB_888: + format = kFormatRGB888; + break; + case HAL_PIXEL_FORMAT_RGB_565: + format = kFormatRGB565; + break; + 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; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + format = kFormatYCbCr420SemiPlanar; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + format = kFormatYCbCr422H2V1SemiPlanar; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_I: + format = kFormatYCbCr422H2V1Packed; + break; + default: + DLOGW("Unsupported format type = %d", source); + return kFormatInvalid; + } + + return format; +} + +LayerBufferS3DFormat HWCLayer::GetS3DFormat(uint32_t s3d_format) { + LayerBufferS3DFormat sdm_s3d_format = kS3dFormatNone; + switch (s3d_format) { + case HAL_NO_3D: + sdm_s3d_format = kS3dFormatNone; + break; + case HAL_3D_SIDE_BY_SIDE_L_R: + sdm_s3d_format = kS3dFormatLeftRight; + break; + case HAL_3D_SIDE_BY_SIDE_R_L: + sdm_s3d_format = kS3dFormatRightLeft; + break; + case HAL_3D_TOP_BOTTOM: + sdm_s3d_format = kS3dFormatTopBottom; + break; + default: + DLOGW("Invalid S3D format %d", s3d_format); + } + return sdm_s3d_format; +} + +DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) { + const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata); + LayerBuffer *layer_buffer = layer->input_buffer; + + if (!meta_data) { + return kErrorNone; + } + + if (meta_data->operation & UPDATE_COLOR_SPACE) { + if (SetCSC(meta_data->colorSpace, &layer->csc) != kErrorNone) { + return kErrorNotSupported; + } + } + + if (meta_data->operation & SET_IGC) { + if (SetIGC(meta_data->igc, &layer->igc) != kErrorNone) { + return kErrorNotSupported; + } + } + + if (meta_data->operation & UPDATE_REFRESH_RATE) { + layer->frame_rate = RoundToStandardFPS(meta_data->refreshrate); + } + + if ((meta_data->operation & PP_PARAM_INTERLACED) && meta_data->interlaced) { + layer_buffer->flags.interlace = true; + } + + if (meta_data->operation & LINEAR_FORMAT) { + layer_buffer->format = GetSDMFormat(INT32(meta_data->linearFormat), 0); + } + + if (meta_data->operation & UPDATE_BUFFER_GEOMETRY) { + int actual_width = pvt_handle->width; + int actual_height = pvt_handle->height; + AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(pvt_handle, actual_width, actual_height); + layer_buffer->width = UINT32(actual_width); + layer_buffer->height = UINT32(actual_height); + } + + if (meta_data->operation & S3D_FORMAT) { + layer_buffer->s3d_format = GetS3DFormat(meta_data->s3dFormat); + } + + return kErrorNone; +} + +DisplayError HWCLayer::SetCSC(ColorSpace_t source, LayerCSC *target) { + switch (source) { + case ITU_R_601: + *target = kCSCLimitedRange601; + break; + case ITU_R_601_FR: + *target = kCSCFullRange601; + break; + case ITU_R_709: + *target = kCSCLimitedRange709; + break; + default: + DLOGE("Unsupported CSC: %d", source); + return kErrorNotSupported; + } + + return kErrorNone; +} + +DisplayError HWCLayer::SetIGC(IGC_t source, LayerIGC *target) { + switch (source) { + case IGC_NotSpecified: + *target = kIGCNotSpecified; + break; + case IGC_sRGB: + *target = kIGCsRGB; + break; + default: + DLOGE("Unsupported IGC: %d", source); + return kErrorNotSupported; + } + + return kErrorNone; +} + +uint32_t HWCLayer::RoundToStandardFPS(uint32_t fps) { + static const uint32_t standard_fps[4] = {30, 24, 48, 60}; + + int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0])); + for (int i = 0; i < count; i++) { + if ((standard_fps[i] - fps) < 2) { + // Most likely used for video, the fps can fluctuate + // Ex: b/w 29 and 30 for 30 fps clip + return standard_fps[i]; + } + } + + return fps; +} + +void HWCLayer::SetComposition(const LayerComposition &source) { + auto composition = HWC2::Composition::Invalid; + switch (source) { + case kCompositionGPU: + composition = HWC2::Composition::Client; + break; + case kCompositionHWCursor: + composition = HWC2::Composition::Cursor; + break; + default: + composition = HWC2::Composition::Device; + break; + } + // Update solid fill composition + if (layer_->composition == kCompositionSDE && layer_->flags.solid_fill != 0) { + composition = HWC2::Composition::SolidColor; + } + if (composition != composition_) { + // Composition changed for this layer + composition_changed_ = true; + composition_ = composition; + } +} +void HWCLayer::PushReleaseFence(int32_t fence) { + release_fences_.push(fence); +} +int32_t HWCLayer::PopReleaseFence(void) { + if (release_fences_.empty()) + return -1; + auto fence = release_fences_.front(); + release_fences_.pop(); + return fence; +} + +} // namespace sdm |