blob: b6bdb21e7223929a713916d2f3c05e873818532e [file] [log] [blame]
/*
* Copyright (c) 2014-2021, 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.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
/*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "hwc_layers.h"
#include <utils/debug.h>
#include <stdint.h>
#include <utility>
#include <cmath>
#include <gr_utils.h>
#define __CLASS__ "HWCLayer"
using aidl::android::hardware::graphics::common::StandardMetadataType;
namespace sdm {
std::atomic<hwc2_layer_t> HWCLayer::next_id_(1);
DisplayError SetCSC(const native_handle_t *handle, ColorMetaData *color_metadata) {
void *hnd = const_cast<native_handle_t *>(handle);
auto error =
gralloc::GetMetaDataValue(hnd, qtigralloc::MetadataType_ColorMetadata.value, color_metadata);
if (error != gralloc::Error::NONE) {
int csc = HAL_CSC_ITU_R_601;
error = gralloc::GetMetaDataValue(hnd, qtigralloc::MetadataType_ColorSpace.value, &csc);
if (error == gralloc::Error::NONE) {
if (csc == HAL_CSC_ITU_R_601_FR || csc == HAL_CSC_ITU_R_709_FR ||
csc == HAL_CSC_ITU_R_2020_FR) {
color_metadata->range = Range_Full;
}
color_metadata->transfer = Transfer_sRGB;
switch (csc) {
case HAL_CSC_ITU_R_601:
case HAL_CSC_ITU_R_601_FR:
// video and display driver uses 601_525
color_metadata->colorPrimaries = ColorPrimaries_BT601_6_525;
break;
case HAL_CSC_ITU_R_709:
case HAL_CSC_ITU_R_709_FR:
color_metadata->colorPrimaries = ColorPrimaries_BT709_5;
break;
case HAL_CSC_ITU_R_2020:
case HAL_CSC_ITU_R_2020_FR:
color_metadata->colorPrimaries = ColorPrimaries_BT2020;
break;
default:
DLOGE("Unsupported CSC: %d", csc);
return kErrorNotSupported;
}
}
}
return kErrorNone;
}
// Returns true when color primary is supported
bool GetColorPrimary(const int32_t &dataspace, ColorPrimaries *color_primary) {
auto standard = dataspace & HAL_DATASPACE_STANDARD_MASK;
bool supported_csc = true;
switch (standard) {
case HAL_DATASPACE_STANDARD_BT709:
*color_primary = ColorPrimaries_BT709_5;
break;
case HAL_DATASPACE_STANDARD_BT601_525:
case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
*color_primary = ColorPrimaries_BT601_6_525;
break;
case HAL_DATASPACE_STANDARD_BT601_625:
case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
*color_primary = ColorPrimaries_BT601_6_625;
break;
case HAL_DATASPACE_STANDARD_DCI_P3:
*color_primary = ColorPrimaries_DCIP3;
break;
case HAL_DATASPACE_STANDARD_BT2020:
*color_primary = ColorPrimaries_BT2020;
break;
default:
DLOGW_IF(kTagClient, "Unsupported Standard Request = %d", standard);
supported_csc = false;
}
return supported_csc;
}
bool GetTransfer(const int32_t &dataspace, GammaTransfer *gamma_transfer) {
auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
bool supported_transfer = true;
switch (transfer) {
case HAL_DATASPACE_TRANSFER_SRGB:
*gamma_transfer = Transfer_sRGB;
break;
case HAL_DATASPACE_TRANSFER_SMPTE_170M:
*gamma_transfer = Transfer_SMPTE_170M;
break;
case HAL_DATASPACE_TRANSFER_ST2084:
*gamma_transfer = Transfer_SMPTE_ST2084;
break;
case HAL_DATASPACE_TRANSFER_HLG:
*gamma_transfer = Transfer_HLG;
break;
case HAL_DATASPACE_TRANSFER_LINEAR:
*gamma_transfer = Transfer_Linear;
break;
case HAL_DATASPACE_TRANSFER_GAMMA2_2:
*gamma_transfer = Transfer_Gamma2_2;
break;
case HAL_DATASPACE_TRANSFER_GAMMA2_8:
*gamma_transfer = Transfer_Gamma2_8;
break;
default:
DLOGW_IF(kTagClient, "Unsupported Transfer Request = %d", transfer);
supported_transfer = false;
}
return supported_transfer;
}
bool GetRange(const int32_t &dataspace, ColorRange *color_range) {
auto range = dataspace & HAL_DATASPACE_RANGE_MASK;
switch (range) {
case HAL_DATASPACE_RANGE_FULL:
*color_range = Range_Full;
break;
case HAL_DATASPACE_RANGE_LIMITED:
*color_range = Range_Limited;
break;
case HAL_DATASPACE_RANGE_EXTENDED:
*color_range = Range_Extended;
break;
default:
DLOGW_IF(kTagClient, "Unsupported Range Request = %d", range);
return false;
}
return true;
}
bool IsHdr(const ColorPrimaries &color_primary, const GammaTransfer &gamma_transfer) {
return (color_primary == ColorPrimaries_BT2020) &&
((gamma_transfer == Transfer_SMPTE_ST2084) || (gamma_transfer == Transfer_HLG));
}
bool IsBT2020(const ColorPrimaries &color_primary) {
switch (color_primary) {
case ColorPrimaries_BT2020:
return true;
break;
default:
return false;
}
}
int32_t TranslateFromLegacyDataspace(const int32_t &legacy_ds) {
int32_t dataspace = legacy_ds;
if (dataspace & 0xffff) {
switch (dataspace & 0xffff) {
case HAL_DATASPACE_SRGB:
dataspace = HAL_DATASPACE_V0_SRGB;
break;
case HAL_DATASPACE_JFIF:
dataspace = HAL_DATASPACE_V0_JFIF;
break;
case HAL_DATASPACE_SRGB_LINEAR:
dataspace = HAL_DATASPACE_V0_SRGB_LINEAR;
break;
case HAL_DATASPACE_BT601_625:
dataspace = HAL_DATASPACE_V0_BT601_625;
break;
case HAL_DATASPACE_BT601_525:
dataspace = HAL_DATASPACE_V0_BT601_525;
break;
case HAL_DATASPACE_BT709:
dataspace = HAL_DATASPACE_V0_BT709;
break;
default:
// unknown legacy dataspace
DLOGW_IF(kTagClient, "Unsupported dataspace type %d", dataspace);
}
}
if (dataspace == HAL_DATASPACE_UNKNOWN) {
dataspace = HAL_DATASPACE_V0_SRGB;
}
return dataspace;
}
// Retrieve ColorMetaData from android_data_space_t (STANDARD|TRANSFER|RANGE)
bool GetSDMColorSpace(const int32_t &dataspace, ColorMetaData *color_metadata) {
bool valid = false;
valid = GetColorPrimary(dataspace, &(color_metadata->colorPrimaries));
if (valid) {
valid = GetTransfer(dataspace, &(color_metadata->transfer));
}
if (valid) {
valid = GetRange(dataspace, &(color_metadata->range));
}
return valid;
}
DisplayError ColorMetadataToDataspace(ColorMetaData color_metadata, Dataspace *dataspace) {
Dataspace primaries, transfer, range = Dataspace::UNKNOWN;
switch (color_metadata.colorPrimaries) {
case ColorPrimaries_BT709_5:
primaries = Dataspace::STANDARD_BT709;
break;
// TODO(user): verify this is equivalent
case ColorPrimaries_BT470_6M:
primaries = Dataspace::STANDARD_BT470M;
break;
case ColorPrimaries_BT601_6_625:
primaries = Dataspace::STANDARD_BT601_625;
break;
case ColorPrimaries_BT601_6_525:
primaries = Dataspace::STANDARD_BT601_525;
break;
case ColorPrimaries_GenericFilm:
primaries = Dataspace::STANDARD_FILM;
break;
case ColorPrimaries_BT2020:
primaries = Dataspace::STANDARD_BT2020;
break;
case ColorPrimaries_AdobeRGB:
primaries = Dataspace::STANDARD_ADOBE_RGB;
break;
case ColorPrimaries_DCIP3:
primaries = Dataspace::STANDARD_DCI_P3;
break;
default:
return kErrorNotSupported;
/*
ColorPrimaries_SMPTE_240M;
ColorPrimaries_SMPTE_ST428;
ColorPrimaries_EBU3213;
*/
}
switch (color_metadata.transfer) {
case Transfer_sRGB:
transfer = Dataspace::TRANSFER_SRGB;
break;
case Transfer_Gamma2_2:
transfer = Dataspace::TRANSFER_GAMMA2_2;
break;
case Transfer_Gamma2_8:
transfer = Dataspace::TRANSFER_GAMMA2_8;
break;
case Transfer_SMPTE_170M:
transfer = Dataspace::TRANSFER_SMPTE_170M;
break;
case Transfer_Linear:
transfer = Dataspace::TRANSFER_LINEAR;
break;
case Transfer_SMPTE_ST2084:
transfer = Dataspace::TRANSFER_ST2084;
break;
case Transfer_HLG:
transfer = Dataspace::TRANSFER_HLG;
break;
default:
return kErrorNotSupported;
/*
Transfer_SMPTE_240M
Transfer_Log
Transfer_Log_Sqrt
Transfer_XvYCC
Transfer_BT1361
Transfer_sYCC
Transfer_BT2020_2_1
Transfer_BT2020_2_2
Transfer_ST_428
*/
}
switch (color_metadata.range) {
case Range_Full:
range = Dataspace::RANGE_FULL;
break;
case Range_Limited:
range = Dataspace::RANGE_LIMITED;
break;
case Range_Extended:
range = Dataspace::RANGE_EXTENDED;
break;
default:
return kErrorNotSupported;
}
*dataspace = (Dataspace)((uint32_t)primaries | (uint32_t)transfer | (uint32_t)range);
return kErrorNone;
}
// Layer operations
HWCLayer::HWCLayer(hwc2_display_t display_id, HWCBufferAllocator *buf_allocator)
: id_(next_id_++), display_id_(display_id), buffer_allocator_(buf_allocator) {
layer_ = new Layer();
geometry_changes_ |= kAdded;
}
HWCLayer::~HWCLayer() {
// Close any fences left for this layer
release_fence_ = nullptr;
if (layer_) {
if (buffer_fd_ >= 0) {
::close(buffer_fd_);
}
delete layer_;
}
}
HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, shared_ptr<Fence> acquire_fence) {
if (!buffer) {
if (client_requested_ == HWC2::Composition::Device ||
client_requested_ == HWC2::Composition::Cursor) {
DLOGW("Invalid buffer handle: %p on layer: %d client requested comp type %d", buffer,
UINT32(id_), client_requested_);
return HWC2::Error::BadParameter;
} else {
return HWC2::Error::None;
}
}
const native_handle_t *handle = reinterpret_cast<const native_handle_t *>(buffer);
void *hnd = const_cast<native_handle_t *>(handle);
int fd;
gralloc::GetMetaDataValue(hnd, qtigralloc::MetadataType_FD.value, &fd);
if (fd < 0) {
return HWC2::Error::BadParameter;
}
LayerBuffer *layer_buffer = &layer_->input_buffer;
int aligned_width, aligned_height;
buffer_allocator_->GetCustomWidthAndHeight(reinterpret_cast<const native_handle_t *>(buffer),
&aligned_width, &aligned_height);
int fmt, flag;
gralloc::GetMetaDataValue(hnd, (int64_t)StandardMetadataType::PIXEL_FORMAT_REQUESTED, &fmt);
gralloc::GetMetaDataValue(hnd, (int64_t)qtigralloc::MetadataType_PrivateFlags.value, &flag);
LayerBufferFormat format = GetSDMFormat(fmt, flag);
if ((format != layer_buffer->format) || (UINT32(aligned_width) != layer_buffer->width) ||
(UINT32(aligned_height) != layer_buffer->height)) {
// Layer buffer geometry has changed.
geometry_changes_ |= kBufferGeometry;
}
layer_buffer->format = format;
layer_buffer->width = UINT32(aligned_width);
layer_buffer->height = UINT32(aligned_height);
auto err_w = gralloc::GetMetaDataValue(hnd, (int64_t)StandardMetadataType::WIDTH,
&layer_buffer->unaligned_width);
if (err_w != gralloc::Error::NONE) {
DLOGE("Failed to retrieve unaligned width");
}
auto err_h = gralloc::GetMetaDataValue(hnd, (int64_t)StandardMetadataType::HEIGHT,
&layer_buffer->unaligned_height);
if (err_h != gralloc::Error::NONE) {
DLOGE("Failed to retrieve unaligned height");
}
int32_t buffer_type;
gralloc::GetMetaDataValue(hnd, (int64_t)qtigralloc::MetadataType_BufferType.value, &buffer_type);
layer_buffer->flags.video = (buffer_type == BUFFER_TYPE_VIDEO) ? true : false;
if (SetMetaData(handle, layer_) != kErrorNone) {
return HWC2::Error::BadLayer;
}
// TZ Protected Buffer - L1
secure_ = (flag & qtigralloc::PRIV_FLAGS_SECURE_BUFFER);
bool secure_camera = secure_ && (flag & qtigralloc::PRIV_FLAGS_CAMERA_WRITE);
bool secure_display = (flag & qtigralloc::PRIV_FLAGS_SECURE_DISPLAY);
if (secure_ != layer_buffer->flags.secure || secure_camera != layer_buffer->flags.secure_camera ||
secure_display != layer_buffer->flags.secure_display) {
// Secure attribute of layer buffer has changed.
layer_->update_mask.set(kSecurity);
}
layer_buffer->flags.secure = secure_;
layer_buffer->flags.secure_camera = secure_camera;
layer_buffer->flags.secure_display = secure_display;
layer_buffer->acquire_fence = acquire_fence;
int buffer_fd = buffer_fd_;
buffer_fd_ = ::dup(fd);
if (buffer_fd >= 0) {
::close(buffer_fd);
}
layer_buffer->planes[0].fd = buffer_fd_;
layer_buffer->planes[0].offset = 0;
auto err =
gralloc::GetMetaDataValue(hnd, QTI_ALIGNED_WIDTH_IN_PIXELS, &layer_buffer->planes[0].stride);
if (err != gralloc::Error::NONE) {
DLOGW("Failed to retrieve aligned width");
}
err = gralloc::GetMetaDataValue(hnd, (int64_t)StandardMetadataType::ALLOCATION_SIZE,
&layer_buffer->size);
if (err != gralloc::Error::NONE) {
DLOGW("Failed to retrieve allocation size");
}
buffer_flipped_ = reinterpret_cast<uint64_t>(handle) != layer_buffer->buffer_id;
layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle);
int64_t hd_id, hd_usage;
err = gralloc::GetMetaDataValue(hnd, (int64_t)StandardMetadataType::BUFFER_ID,
&layer_buffer->handle_id);
if (err != gralloc::Error::NONE) {
DLOGW("Failed to retrieve buffer id");
}
err = gralloc::GetMetaDataValue(hnd, (int64_t)StandardMetadataType::USAGE, &layer_buffer->usage);
if (err != gralloc::Error::NONE) {
DLOGW("Failed to retrieve handle usage");
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
surface_updated_ = true;
if ((damage.numRects == 1) && (damage.rects[0].bottom == 0) && (damage.rects[0].right == 0)) {
surface_updated_ = false;
}
if (!layer_->flags.updating && surface_updated_) {
layer_->update_mask.set(kSurfaceInvalidate);
}
// Check if there is an update in SurfaceDamage rects.
if (layer_->dirty_regions.size() != damage.numRects) {
layer_->update_mask.set(kSurfaceInvalidate);
} else {
for (uint32_t j = 0; j < damage.numRects; j++) {
LayerRect damage_rect;
SetRect(damage.rects[j], &damage_rect);
if (damage_rect != layer_->dirty_regions.at(j)) {
layer_->update_mask.set(kSurfaceDamage);
break;
}
}
}
SetDirtyRegions(damage);
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerBlendMode(HWC2::BlendMode mode) {
LayerBlending blending = kBlendingPremultiplied;
switch (mode) {
case HWC2::BlendMode::Coverage:
blending = kBlendingCoverage;
break;
case HWC2::BlendMode::Premultiplied:
blending = kBlendingPremultiplied;
break;
case HWC2::BlendMode::None:
blending = kBlendingOpaque;
break;
default:
return HWC2::Error::BadParameter;
}
if (layer_->blending != blending) {
geometry_changes_ |= kBlendMode;
layer_->blending = blending;
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerColor(hwc_color_t color) {
if (client_requested_ != HWC2::Composition::SolidColor) {
return HWC2::Error::None;
}
if (layer_->solid_fill_color != GetUint32Color(color)) {
layer_->solid_fill_color = GetUint32Color(color);
layer_->update_mask.set(kSurfaceInvalidate);
surface_updated_ = true;
} else {
surface_updated_ = false;
}
layer_->input_buffer.format = kFormatARGB8888;
DLOGV_IF(kTagClient, "[%" PRIu64 "][%" PRIu64 "] Layer color set to %x", display_id_, id_,
layer_->solid_fill_color);
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerCompositionType(HWC2::Composition type) {
// Validation is required when the client changes the composition type
if ((type != client_requested_) || (type != device_selected_) ||
(type == HWC2::Composition::Client)) {
layer_->update_mask.set(kClientCompRequest);
}
client_requested_ = type;
client_requested_orig_ = type;
switch (type) {
case HWC2::Composition::Client:
break;
case HWC2::Composition::Device:
// We try and default to this in SDM
break;
case HWC2::Composition::SolidColor:
break;
case HWC2::Composition::Cursor:
break;
case HWC2::Composition::Invalid:
return HWC2::Error::BadParameter;
default:
return HWC2::Error::Unsupported;
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerDataspace(int32_t dataspace) {
// Map deprecated dataspace values to appropriate new enums
dataspace = TranslateFromLegacyDataspace(dataspace);
// cache the dataspace, to be used later to update SDM ColorMetaData
if (dataspace_ != dataspace) {
geometry_changes_ |= kDataspace;
dataspace_ = dataspace;
if (layer_->input_buffer.buffer_id) {
ValidateAndSetCSC(reinterpret_cast<native_handle_t *>(layer_->input_buffer.buffer_id));
}
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
LayerRect dst_rect = {};
SetRect(frame, &dst_rect);
if (dst_rect_ != dst_rect) {
geometry_changes_ |= kDisplayFrame;
dst_rect_ = dst_rect;
}
return HWC2::Error::None;
}
void HWCLayer::ResetPerFrameData() {
layer_->dst_rect = dst_rect_;
layer_->transform = layer_transform_;
}
HWC2::Error HWCLayer::SetCursorPosition(int32_t x, int32_t y) {
hwc_rect_t frame = {};
frame.left = x;
frame.top = y;
frame.right = x + INT(layer_->dst_rect.right - layer_->dst_rect.left);
frame.bottom = y + INT(layer_->dst_rect.bottom - layer_->dst_rect.top);
SetLayerDisplayFrame(frame);
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
if (alpha < 0.0f || alpha > 1.0f) {
return HWC2::Error::BadParameter;
}
uint8_t kMaxPlaneAlpha = 255;
// Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
uint8_t plane_alpha = static_cast<uint8_t>(std::round(float(kMaxPlaneAlpha) * alpha));
// if alpha lies in the range (0.998, 1), plane_alpha becomes 255 when rounded off,
// while alpha < 1. HWC knows layer as opaque and marks punch hole for that layer in fbt,
// while SF knows it as non-opaque and doesn't create punch hole.
if ((plane_alpha == kMaxPlaneAlpha) && (alpha < 1.0f)) {
plane_alpha = (kMaxPlaneAlpha - 1);
}
if (layer_->plane_alpha != plane_alpha) {
geometry_changes_ |= kPlaneAlpha;
layer_->plane_alpha = plane_alpha;
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerSourceCrop(hwc_frect_t crop) {
LayerRect src_rect = {};
SetRect(crop, &src_rect);
non_integral_source_crop_ =
((crop.left != roundf(crop.left)) || (crop.top != roundf(crop.top)) ||
(crop.right != roundf(crop.right)) || (crop.bottom != roundf(crop.bottom)));
if (non_integral_source_crop_) {
DLOGV_IF(kTagClient, "Crop: LTRB %f %f %f %f", crop.left, crop.top, crop.right, crop.bottom);
}
if (layer_->src_rect != src_rect) {
geometry_changes_ |= kSourceCrop;
layer_->src_rect = src_rect;
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerTransform(HWC2::Transform transform) {
LayerTransform layer_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.flip_horizontal = true;
layer_transform.flip_vertical = true;
break;
case HWC2::Transform::Rotate270:
layer_transform.rotation = 90.0f;
layer_transform.flip_horizontal = true;
layer_transform.flip_vertical = true;
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;
case HWC2::Transform::None:
break;
default:
// bad transform
return HWC2::Error::BadParameter;
}
if (layer_transform_ != layer_transform) {
geometry_changes_ |= kTransform;
layer_transform_ = layer_transform;
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerVisibleRegion(hwc_region_t visible) {
layer_->visible_regions.clear();
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) {
if (z_ != z) {
geometry_changes_ |= kZOrder;
z_ = z;
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerType(IQtiComposerClient::LayerType type) {
LayerTypes layer_type = kLayerUnknown;
switch (type) {
case IQtiComposerClient::LayerType::UNKNOWN:
layer_type = kLayerUnknown;
break;
case IQtiComposerClient::LayerType::APP:
layer_type = kLayerApp;
break;
case IQtiComposerClient::LayerType::GAME:
layer_type = kLayerGame;
break;
case IQtiComposerClient::LayerType::BROWSER:
layer_type = kLayerBrowser;
break;
default:
DLOGW("Unsupported layer type %d", layer_type);
break;
}
type_ = layer_type;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerFlag(IQtiComposerClient::LayerFlag flag) {
compatible_ = (flag == IQtiComposerClient::LayerFlag::COMPATIBLE);
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerColorTransform(const float *matrix) {
if (std::memcmp(matrix, layer_->color_transform_matrix, sizeof(layer_->color_transform_matrix))) {
std::memcpy(layer_->color_transform_matrix, matrix, sizeof(layer_->color_transform_matrix));
layer_->update_mask.set(kColorTransformUpdate);
color_transform_matrix_set_ = true;
if (!std::memcmp(matrix, kIdentityMatrix, sizeof(kIdentityMatrix))) {
color_transform_matrix_set_ = false;
}
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerPerFrameMetadata(uint32_t num_elements,
const PerFrameMetadataKey *keys,
const float *metadata) {
auto old_mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
auto old_content_light = layer_->input_buffer.color_metadata.contentLightLevel;
auto &mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
auto &content_light = layer_->input_buffer.color_metadata.contentLightLevel;
for (uint32_t i = 0; i < num_elements; i++) {
switch (keys[i]) {
case PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X:
mastering_display.colorVolumeSEIEnabled = true;
mastering_display.primaries.rgbPrimaries[0][0] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y:
mastering_display.primaries.rgbPrimaries[0][1] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X:
mastering_display.primaries.rgbPrimaries[1][0] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y:
mastering_display.primaries.rgbPrimaries[1][1] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X:
mastering_display.primaries.rgbPrimaries[2][0] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y:
mastering_display.primaries.rgbPrimaries[2][1] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::WHITE_POINT_X:
mastering_display.primaries.whitePoint[0] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::WHITE_POINT_Y:
mastering_display.primaries.whitePoint[1] = UINT32(metadata[i] * 50000);
break;
case PerFrameMetadataKey::MAX_LUMINANCE:
mastering_display.maxDisplayLuminance = UINT32(metadata[i]);
break;
case PerFrameMetadataKey::MIN_LUMINANCE:
mastering_display.minDisplayLuminance = UINT32(metadata[i] * 10000);
break;
case PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL:
content_light.lightLevelSEIEnabled = true;
content_light.maxContentLightLevel = UINT32(metadata[i]);
break;
case PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL:
content_light.minPicAverageLightLevel = UINT32(metadata[i]);
break;
default:
break;
}
}
if ((!SameConfig(&old_mastering_display, &mastering_display, UINT32(sizeof(MasteringDisplay)))) ||
(!SameConfig(&old_content_light, &content_light, UINT32(sizeof(ContentLightLevel))))) {
layer_->update_mask.set(kContentMetadata);
geometry_changes_ |= kDataspace;
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerPerFrameMetadataBlobs(uint32_t num_elements,
const PerFrameMetadataKey *keys,
const uint32_t *sizes,
const uint8_t *metadata) {
if (!keys || !sizes || !metadata) {
DLOGE("metadata or sizes or keys is null");
return HWC2::Error::BadParameter;
}
ColorMetaData &color_metadata = layer_->input_buffer.color_metadata;
for (uint32_t i = 0; i < num_elements; i++) {
switch (keys[i]) {
case PerFrameMetadataKey::HDR10_PLUS_SEI:
if (sizes[i] > HDR_DYNAMIC_META_DATA_SZ) {
DLOGE("Size of HDR10_PLUS_SEI = %d", sizes[i]);
return HWC2::Error::BadParameter;
}
// if dynamic metadata changes, store and set needs validate
if (!SameConfig(static_cast<const uint8_t *>(color_metadata.dynamicMetaDataPayload),
metadata, sizes[i])) {
geometry_changes_ |= kDataspace;
color_metadata.dynamicMetaDataValid = true;
color_metadata.dynamicMetaDataLen = sizes[i];
std::memcpy(color_metadata.dynamicMetaDataPayload, metadata, sizes[i]);
layer_->update_mask.set(kContentMetadata);
}
break;
default:
DLOGW("Invalid key = %d", keys[i]);
return HWC2::Error::BadParameter;
}
}
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 & qtigralloc::PRIV_FLAGS_UBWC_ALIGNED) {
switch (source) {
case static_cast<int>(PixelFormat::RGBA_8888):
format = kFormatRGBA8888Ubwc;
break;
case static_cast<int>(PixelFormat::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;
case static_cast<int>(PixelFormat::RGBA_1010102):
format = kFormatRGBA1010102Ubwc;
break;
case HAL_PIXEL_FORMAT_RGBX_1010102:
format = kFormatRGBX1010102Ubwc;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
format = kFormatYCbCr420TP10Ubwc;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
format = kFormatYCbCr420P010Ubwc;
break;
case HAL_PIXEL_FORMAT_RGBA_FP16:
format = kFormatRGBA16161616FUbwc;
break;
default:
DLOGW("Unsupported format type for UBWC: %d", source);
return kFormatInvalid;
}
return format;
}
switch (source) {
case static_cast<int>(PixelFormat::RGBA_8888):
format = kFormatRGBA8888;
break;
case HAL_PIXEL_FORMAT_RGBA_5551:
format = kFormatRGBA5551;
break;
case HAL_PIXEL_FORMAT_RGBA_4444:
format = kFormatRGBA4444;
break;
case static_cast<int>(PixelFormat::BGRA_8888):
format = kFormatBGRA8888;
break;
case static_cast<int>(PixelFormat::RGBX_8888):
format = kFormatRGBX8888;
break;
case HAL_PIXEL_FORMAT_BGRX_8888:
format = kFormatBGRX8888;
break;
case static_cast<int>(PixelFormat::RGB_888):
format = kFormatRGB888;
break;
case HAL_PIXEL_FORMAT_BGR_888:
format = kFormatBGR888;
break;
case static_cast<int>(PixelFormat::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 static_cast<int>(PixelFormat::YV12):
format = kFormatYCrCb420PlanarStride16;
break;
case static_cast<int>(PixelFormat::YCRCB_420_SP):
format = kFormatYCrCb420SemiPlanar;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
format = kFormatYCbCr420SemiPlanar;
break;
case static_cast<int>(PixelFormat::YCBCR_422_SP):
format = kFormatYCbCr422H2V1SemiPlanar;
break;
case HAL_PIXEL_FORMAT_YCbCr_422_I:
format = kFormatYCbCr422H2V1Packed;
break;
case HAL_PIXEL_FORMAT_CbYCrY_422_I:
format = kFormatCbYCrY422H2V1Packed;
break;
case static_cast<int>(PixelFormat::RGBA_1010102):
format = kFormatRGBA1010102;
break;
case HAL_PIXEL_FORMAT_ARGB_2101010:
format = kFormatARGB2101010;
break;
case HAL_PIXEL_FORMAT_RGBX_1010102:
format = kFormatRGBX1010102;
break;
case HAL_PIXEL_FORMAT_XRGB_2101010:
format = kFormatXRGB2101010;
break;
case HAL_PIXEL_FORMAT_BGRA_1010102:
format = kFormatBGRA1010102;
break;
case HAL_PIXEL_FORMAT_ABGR_2101010:
format = kFormatABGR2101010;
break;
case HAL_PIXEL_FORMAT_BGRX_1010102:
format = kFormatBGRX1010102;
break;
case HAL_PIXEL_FORMAT_XBGR_2101010:
format = kFormatXBGR2101010;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_P010:
format = kFormatYCbCr420P010;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
format = kFormatYCbCr420TP10Ubwc;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
format = kFormatYCbCr420P010Ubwc;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS:
format = kFormatYCbCr420P010Venus;
break;
case static_cast<int>(PixelFormat::RGBA_FP16):
format = kFormatRGBA16161616F;
break;
default:
DLOGW("Unsupported format type = %d", source);
return kFormatInvalid;
}
return format;
}
void HWCLayer::GetUBWCStatsFromMetaData(UBWCStats *cr_stats, UbwcCrStatsVector *cr_vec) {
// TODO(user): Check if we can use UBWCStats directly
// in layer_buffer or copy directly to Vector
if (cr_stats->bDataValid) {
switch (cr_stats->version) {
case UBWC_4_0:
case UBWC_3_0:
case UBWC_2_0:
cr_vec->push_back(std::make_pair(32, cr_stats->ubwc_stats.nCRStatsTile32));
cr_vec->push_back(std::make_pair(64, cr_stats->ubwc_stats.nCRStatsTile64));
cr_vec->push_back(std::make_pair(96, cr_stats->ubwc_stats.nCRStatsTile96));
cr_vec->push_back(std::make_pair(128, cr_stats->ubwc_stats.nCRStatsTile128));
cr_vec->push_back(std::make_pair(160, cr_stats->ubwc_stats.nCRStatsTile160));
cr_vec->push_back(std::make_pair(192, cr_stats->ubwc_stats.nCRStatsTile192));
cr_vec->push_back(std::make_pair(256, cr_stats->ubwc_stats.nCRStatsTile256));
break;
default:
DLOGW("Invalid UBWC Version %d", cr_stats->version);
break;
} // switch(cr_stats->version)
} // if (cr_stats->bDatvalid)
}
DisplayError HWCLayer::SetMetaData(const native_handle_t *pvt_handle, Layer *layer) {
LayerBuffer *layer_buffer = &layer->input_buffer;
void *handle = const_cast<native_handle_t *>(pvt_handle);
std::string name = "";
gralloc::GetMetaDataValue(handle, android::gralloc4::MetadataType_Name.value, &name);
name_ = name;
float fps = 0;
uint32_t frame_rate = layer->frame_rate;
if (gralloc::GetMetaDataValue(handle, qtigralloc::MetadataType_RefreshRate.value, &fps) ==
gralloc::Error::NONE) {
frame_rate = (fps != 0) ? RoundToStandardFPS(fps) : layer->frame_rate;
has_metadata_refresh_rate_ = true;
}
int32_t interlaced = 0;
gralloc::GetMetaDataValue(handle, qtigralloc::MetadataType_PPParamInterlaced.value, &interlaced);
bool interlace = interlaced ? true : false;
if (interlace != layer_buffer->flags.interlace) {
DLOGI("Layer buffer interlaced metadata has changed. old=%d, new=%d",
layer_buffer->flags.interlace, interlace);
}
uint32_t linear_format = 0;
if (gralloc::GetMetaDataValue(handle, qtigralloc::MetadataType_LinearFormat.value,
&linear_format) == gralloc::Error::NONE) {
layer_buffer->format = GetSDMFormat(INT32(linear_format), 0);
if (layer_buffer->format == kFormatInvalid) {
return kErrorNotSupported;
}
}
if ((interlace != layer_buffer->flags.interlace) || (frame_rate != layer->frame_rate)) {
// Layer buffer metadata has changed.
layer->frame_rate = frame_rate;
layer_buffer->flags.interlace = interlace;
layer_->update_mask.set(kMetadataUpdate);
}
// Check if metadata is set
struct UBWCStats cr_stats[NUM_UBWC_CR_STATS_LAYERS] = {};
for (int i = 0; i < NUM_UBWC_CR_STATS_LAYERS; i++) {
layer_buffer->ubwc_crstats[i].clear();
}
if (gralloc::GetMetaDataValue(handle, qtigralloc::MetadataType_UBWCCRStatsInfo.value, cr_stats) ==
gralloc::Error::NONE) {
// Only copy top layer for now as only top field for interlaced is used
GetUBWCStatsFromMetaData(&cr_stats[0], &(layer_buffer->ubwc_crstats[0]));
if (cr_stats[0].version < 0 || cr_stats[0].version >= UBWC_MAX_VERSION) {
return kErrorNotSupported;
}
}
uint32_t single_buffer = 0;
gralloc::GetMetaDataValue(handle, qtigralloc::MetadataType_SingleBufferMode.value,
&single_buffer);
single_buffer_ = (single_buffer == 1);
// Handle colorMetaData / Dataspace handling now
ValidateAndSetCSC(static_cast<native_handle_t *>(handle));
int extended_md_set = qtigralloc::getMetadataState(handle, QTI_CUSTOM_CONTENT_METADATA);
if (extended_md_set > 0) {
std::shared_ptr<CustomContentMetadata> dv_md = std::make_shared<CustomContentMetadata>();
int err = buffer_allocator_->GetCustomContentMetadata(handle, dv_md.get());
if (!err) {
if (!layer_buffer->extended_content_metadata ||
dv_md->size != layer_buffer->extended_content_metadata->size ||
!SameConfig(layer_buffer->extended_content_metadata->metadataPayload,
dv_md->metadataPayload, dv_md->size)) {
layer_buffer->extended_content_metadata = dv_md;
layer_->update_mask.set(kContentMetadata);
}
}
} else if (layer_buffer->extended_content_metadata) {
// Buffer switch scenario - cleanup old metadata
layer_buffer->extended_content_metadata = nullptr;
layer_->update_mask.set(kContentMetadata);
}
if (!ignore_sdr_histogram_md_ ||
IsHdr(layer_buffer->color_metadata.colorPrimaries, layer_buffer->color_metadata.transfer)) {
VideoHistogramMetadata histogram = {};
if (layer_->update_mask.test(kContentMetadata) == false &&
gralloc::GetMetaDataValue(static_cast<native_handle_t *>(handle),
qtigralloc::MetadataType_VideoHistogramStats.value,
&histogram) == gralloc::Error::NONE) {
uint32_t bins = histogram.stat_len / sizeof(histogram.stats_info[0]);
layer_buffer->hist_data.display_width = layer_buffer->unaligned_width;
layer_buffer->hist_data.display_height = layer_buffer->unaligned_height;
if (histogram.stat_len <= sizeof(histogram.stats_info) && bins > 0) {
layer_buffer->hist_data.stats_info.clear();
layer_buffer->hist_data.stats_info.reserve(bins);
for (uint32_t i = 0; i < bins; i++) {
layer_buffer->hist_data.stats_info.push_back(histogram.stats_info[i]);
}
layer_buffer->hist_data.stats_valid = true;
layer_->update_mask.set(kContentMetadata);
}
}
}
layer_buffer->timestamp_data.valid = false;
int timestamp_set = qtigralloc::getMetadataState(handle, QTI_VIDEO_TS_INFO);
if (timestamp_set > 0) {
VideoTimestampInfo timestamp_info = {};
int err = static_cast<int>(qtigralloc::get(handle, QTI_VIDEO_TS_INFO, &timestamp_info));
if (!err && timestamp_info.enable) {
layer_buffer->timestamp_data.valid = true;
layer_buffer->timestamp_data.frame_number = timestamp_info.frame_number;
layer_buffer->timestamp_data.frame_timestamp_us = timestamp_info.frame_timestamp_us;
}
}
return kErrorNone;
}
bool HWCLayer::IsDataSpaceSupported() {
if (client_requested_ != HWC2::Composition::Device &&
client_requested_ != HWC2::Composition::Cursor) {
// Layers marked for GPU can have any dataspace
return true;
}
return dataspace_supported_;
}
void HWCLayer::ValidateAndSetCSC(const native_handle_t *handle) {
LayerBuffer *layer_buffer = &layer_->input_buffer;
bool use_color_metadata = true;
ColorMetaData csc = {};
if (dataspace_ != HAL_DATASPACE_UNKNOWN) {
use_color_metadata = false;
bool valid_csc = GetSDMColorSpace(dataspace_, &csc);
if (!valid_csc) {
dataspace_supported_ = false;
return;
}
if (layer_buffer->color_metadata.transfer != csc.transfer ||
layer_buffer->color_metadata.colorPrimaries != csc.colorPrimaries ||
layer_buffer->color_metadata.range != csc.range) {
// ColorMetadata updated. Needs validate.
layer_->update_mask.set(kMetadataUpdate);
// if we are here here, update the sdm layer csc.
layer_buffer->color_metadata.transfer = csc.transfer;
layer_buffer->color_metadata.colorPrimaries = csc.colorPrimaries;
layer_buffer->color_metadata.range = csc.range;
}
}
if (IsBT2020(layer_buffer->color_metadata.colorPrimaries)) {
// android_dataspace_t doesnt support mastering display and light levels
// so retrieve it from metadata for BT2020(HDR)
use_color_metadata = true;
}
if (use_color_metadata) {
ColorMetaData new_metadata = layer_buffer->color_metadata;
if (sdm::SetCSC(handle, &new_metadata) == kErrorNone) {
// If dataspace is KNOWN, overwrite the gralloc metadata CSC using the previously derived CSC
// from dataspace.
if (dataspace_ != HAL_DATASPACE_UNKNOWN) {
new_metadata.colorPrimaries = layer_buffer->color_metadata.colorPrimaries;
new_metadata.transfer = layer_buffer->color_metadata.transfer;
new_metadata.range = layer_buffer->color_metadata.range;
}
if ((layer_buffer->color_metadata.colorPrimaries != new_metadata.colorPrimaries) ||
(layer_buffer->color_metadata.transfer != new_metadata.transfer) ||
(layer_buffer->color_metadata.range != new_metadata.range)) {
layer_buffer->color_metadata.colorPrimaries = new_metadata.colorPrimaries;
layer_buffer->color_metadata.transfer = new_metadata.transfer;
layer_buffer->color_metadata.range = new_metadata.range;
layer_->update_mask.set(kMetadataUpdate);
}
if (layer_buffer->color_metadata.matrixCoefficients != new_metadata.matrixCoefficients) {
layer_buffer->color_metadata.matrixCoefficients = new_metadata.matrixCoefficients;
layer_->update_mask.set(kMetadataUpdate);
}
DLOGV_IF(kTagClient,
"Layer id = %d ColorVolEnabled = %d ContentLightLevelEnabled = %d "
"cRIEnabled = %d Dynamic Metadata valid = %d size = %d",
UINT32(id_), new_metadata.masteringDisplayInfo.colorVolumeSEIEnabled,
new_metadata.contentLightLevel.lightLevelSEIEnabled, new_metadata.cRI.criEnabled,
new_metadata.dynamicMetaDataValid, new_metadata.dynamicMetaDataLen);
// Read color metadata from gralloc handle if it's enabled by clients, this will override the
// values set using the Composer API's(SetLayerPerFrameMetaData)
if (new_metadata.masteringDisplayInfo.colorVolumeSEIEnabled &&
!SameConfig(&new_metadata.masteringDisplayInfo,
&layer_buffer->color_metadata.masteringDisplayInfo,
UINT32(sizeof(MasteringDisplay)))) {
layer_buffer->color_metadata.masteringDisplayInfo = new_metadata.masteringDisplayInfo;
layer_->update_mask.set(kContentMetadata);
}
if (new_metadata.contentLightLevel.lightLevelSEIEnabled &&
!SameConfig(&new_metadata.contentLightLevel,
&layer_buffer->color_metadata.contentLightLevel,
UINT32(sizeof(ContentLightLevel)))) {
layer_buffer->color_metadata.contentLightLevel = new_metadata.contentLightLevel;
layer_->update_mask.set(kContentMetadata);
}
if (new_metadata.cRI.criEnabled &&
!SameConfig(&new_metadata.cRI, &layer_buffer->color_metadata.cRI,
UINT32(sizeof(ColorRemappingInfo)))) {
layer_buffer->color_metadata.cRI = new_metadata.cRI;
layer_->update_mask.set(kMetadataUpdate);
}
if (new_metadata.dynamicMetaDataValid &&
((new_metadata.dynamicMetaDataLen != layer_buffer->color_metadata.dynamicMetaDataLen) ||
!SameConfig(layer_buffer->color_metadata.dynamicMetaDataPayload,
new_metadata.dynamicMetaDataPayload, new_metadata.dynamicMetaDataLen))) {
layer_buffer->color_metadata.dynamicMetaDataValid = true;
layer_buffer->color_metadata.dynamicMetaDataLen = new_metadata.dynamicMetaDataLen;
std::memcpy(layer_buffer->color_metadata.dynamicMetaDataPayload,
new_metadata.dynamicMetaDataPayload, new_metadata.dynamicMetaDataLen);
layer_->update_mask.set(kContentMetadata);
}
} else {
dataspace_supported_ = false;
return;
}
}
dataspace_supported_ = true;
}
uint32_t HWCLayer::RoundToStandardFPS(float fps) {
static const int32_t standard_fps[4] = {24, 30, 48, 60};
int32_t frame_rate = (uint32_t)(fps);
int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
for (int i = 0; i < count; i++) {
if ((standard_fps[i] - frame_rate) < 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 frame_rate;
}
void HWCLayer::SetComposition(const LayerComposition &sdm_composition) {
auto hwc_composition = HWC2::Composition::Invalid;
switch (sdm_composition) {
case kCompositionGPU:
hwc_composition = HWC2::Composition::Client;
break;
case kCompositionCursor:
hwc_composition = HWC2::Composition::Cursor;
break;
default:
hwc_composition = HWC2::Composition::Device;
break;
}
// Update solid fill composition
if (sdm_composition == kCompositionSDE && layer_->flags.solid_fill != 0) {
hwc_composition = HWC2::Composition::SolidColor;
}
device_selected_ = hwc_composition;
return;
}
shared_ptr<Fence> HWCLayer::GetReleaseFence() {
return release_fence_;
}
void HWCLayer::SetReleaseFence(const shared_ptr<Fence> &release_fence) {
release_fence_ = release_fence;
}
bool HWCLayer::IsRotationPresent() {
return ((layer_->transform.rotation != 0.0f) || layer_->transform.flip_horizontal ||
layer_->transform.flip_vertical);
}
bool HWCLayer::IsScalingPresent() {
uint32_t src_width = static_cast<uint32_t>(layer_->src_rect.right - layer_->src_rect.left);
uint32_t src_height = static_cast<uint32_t>(layer_->src_rect.bottom - layer_->src_rect.top);
uint32_t dst_width = static_cast<uint32_t>(layer_->dst_rect.right - layer_->dst_rect.left);
uint32_t dst_height = static_cast<uint32_t>(layer_->dst_rect.bottom - layer_->dst_rect.top);
if ((layer_->transform.rotation == 90.0) || (layer_->transform.rotation == 270.0)) {
std::swap(src_width, src_height);
}
return ((src_width != dst_width) || (dst_height != src_height));
}
void HWCLayer::SetDirtyRegions(hwc_region_t surface_damage) {
layer_->dirty_regions.clear();
for (uint32_t i = 0; i < surface_damage.numRects; i++) {
LayerRect rect;
SetRect(surface_damage.rects[i], &rect);
layer_->dirty_regions.push_back(rect);
}
}
void HWCLayer::SetLayerAsMask() {
layer_->input_buffer.flags.mask_layer = true;
DLOGV_IF(kTagClient,
" Layer Id: "
"[%" PRIu64 "]",
id_);
}
void HWCLayer::ResetGeometryChanges() {
geometry_changes_ = GeometryChanges::kNone;
layer_->geometry_changes = GeometryChanges::kNone;
}
} // namespace sdm