summaryrefslogtreecommitdiff
path: root/sdm/libs/hwc2/hwc_layers.cpp
diff options
context:
space:
mode:
authorNaseer Ahmed <naseer@codeaurora.org>2016-03-12 02:03:48 -0500
committerNaseer Ahmed <naseer@codeaurora.org>2016-04-28 17:42:00 -0400
commitb92e73fc10b5fefa69ef93031a91412527d56971 (patch)
tree50cec063f21015e63dbbf5d502e43ba253059c2c /sdm/libs/hwc2/hwc_layers.cpp
parentc14b2088b079c637cea23dd97d2f68fd7ed624b8 (diff)
downloaddisplay-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.cpp500
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