| /* |
| * Copyright 2021 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 "Layer.h" |
| |
| #include <android-base/unique_fd.h> |
| #include <sync/sync.h> |
| |
| #include <atomic> |
| |
| namespace android { |
| namespace { |
| |
| std::atomic<hwc2_layer_t> sNextId{1}; |
| |
| } // namespace |
| |
| Layer::Layer() : mId(sNextId++) {} |
| |
| HWC2::Error Layer::setBuffer(buffer_handle_t buffer, int32_t fence) { |
| DEBUG_LOG("%s: layer:%" PRIu64 " buffer:%p fence:%" PRIu32, __FUNCTION__, mId, |
| buffer, fence); |
| mBuffer.setBuffer(buffer); |
| mBuffer.setFence(base::unique_fd(fence)); |
| return HWC2::Error::None; |
| } |
| |
| buffer_handle_t Layer::waitAndGetBuffer() { |
| DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId); |
| |
| base::unique_fd fence = mBuffer.getFence(); |
| if (fence.ok()) { |
| int err = sync_wait(fence.get(), 3000); |
| if (err < 0 && errno == ETIME) { |
| ALOGE("%s waited on fence %" PRId32 " for 3000 ms", __FUNCTION__, |
| fence.get()); |
| } |
| } |
| |
| return mBuffer.getBuffer(); |
| } |
| |
| HWC2::Error Layer::setCursorPosition(int32_t /*x*/, int32_t /*y*/) { |
| DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId); |
| |
| if (mCompositionType != HWC2::Composition::Cursor) { |
| ALOGE("%s: CompositionType not Cursor type", __FUNCTION__); |
| return HWC2::Error::BadLayer; |
| } |
| |
| return HWC2::Error::None; |
| } |
| |
| HWC2::Error Layer::setSurfaceDamage(hwc_region_t /*damage*/) { |
| DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId); |
| |
| return HWC2::Error::None; |
| } |
| |
| HWC2::Error Layer::setBlendMode(int32_t m) { |
| const auto blendMode = static_cast<HWC2::BlendMode>(m); |
| const auto blendModeString = to_string(blendMode); |
| DEBUG_LOG("%s layer:%" PRIu64 " blend mode:%s", __FUNCTION__, mId, |
| blendModeString.c_str()); |
| |
| mBlendMode = blendMode; |
| return HWC2::Error::None; |
| } |
| |
| HWC2::BlendMode Layer::getBlendMode() const { |
| const auto blendMode = mBlendMode; |
| const auto blendModeString = to_string(blendMode); |
| DEBUG_LOG("%s layer:%" PRIu64 " blend mode:%s", __FUNCTION__, mId, |
| blendModeString.c_str()); |
| |
| return blendMode; |
| } |
| |
| HWC2::Error Layer::setColor(hwc_color_t color) { |
| DEBUG_LOG("%s layer:%" PRIu64 " color-r:%d color-g:%d color-b:%d color-a:%d)", |
| __FUNCTION__, mId, color.r, color.g, color.b, color.a); |
| |
| mColor = color; |
| return HWC2::Error::None; |
| } |
| |
| hwc_color_t Layer::getColor() const { |
| auto color = mColor; |
| DEBUG_LOG("%s layer:%" PRIu64 " color-r:%d color-g:%d color-b:%d color-a:%d)", |
| __FUNCTION__, mId, color.r, color.g, color.b, color.a); |
| |
| return color; |
| } |
| |
| HWC2::Error Layer::setCompositionTypeEnum(HWC2::Composition compositionType) { |
| const auto compositionTypeString = to_string(compositionType); |
| DEBUG_LOG("%s layer:%" PRIu64 " composition type:%s", __FUNCTION__, mId, |
| compositionTypeString.c_str()); |
| |
| mCompositionType = compositionType; |
| return HWC2::Error::None; |
| } |
| |
| HWC2::Error Layer::setCompositionType(int32_t type) { |
| const auto compositionType = static_cast<HWC2::Composition>(type); |
| return setCompositionTypeEnum(compositionType); |
| } |
| |
| HWC2::Composition Layer::getCompositionType() const { |
| const auto compositionType = mCompositionType; |
| const auto compositionTypeString = to_string(compositionType); |
| DEBUG_LOG("%s layer:%" PRIu64 " composition type:%s", __FUNCTION__, mId, |
| compositionTypeString.c_str()); |
| |
| return compositionType; |
| } |
| |
| HWC2::Error Layer::setDataspace(int32_t) { |
| DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId); |
| |
| return HWC2::Error::None; |
| } |
| |
| HWC2::Error Layer::setDisplayFrame(hwc_rect_t frame) { |
| DEBUG_LOG("%s layer:%" PRIu64 |
| " display frame rect-left:%d rect-top:%d rect-right:%d rect-bot:%d", |
| __FUNCTION__, mId, frame.left, frame.top, frame.right, |
| frame.bottom); |
| |
| mDisplayFrame = frame; |
| return HWC2::Error::None; |
| } |
| |
| hwc_rect_t Layer::getDisplayFrame() const { |
| auto frame = mDisplayFrame; |
| DEBUG_LOG("%s layer:%" PRIu64 |
| " display frame rect-left:%d rect-top:%d rect-right:%d rect-bot:%d", |
| __FUNCTION__, mId, frame.left, frame.top, frame.right, |
| frame.bottom); |
| |
| return frame; |
| } |
| |
| HWC2::Error Layer::setPlaneAlpha(float alpha) { |
| DEBUG_LOG("%s layer:%" PRIu64 "alpha:%f", __FUNCTION__, mId, alpha); |
| |
| mPlaneAlpha = alpha; |
| return HWC2::Error::None; |
| } |
| |
| float Layer::getPlaneAlpha() const { |
| auto alpha = mPlaneAlpha; |
| DEBUG_LOG("%s layer:%" PRIu64 "alpha:%f", __FUNCTION__, mId, alpha); |
| |
| return alpha; |
| } |
| |
| HWC2::Error Layer::setSidebandStream(const native_handle_t* stream) { |
| DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId); |
| |
| mSidebandStream = stream; |
| return HWC2::Error::None; |
| } |
| |
| HWC2::Error Layer::setSourceCrop(hwc_frect_t crop) { |
| DEBUG_LOG("%s layer:%" PRIu64 |
| "crop rect-left:%f rect-top:%f rect-right:%f rect-bot:%f", |
| __FUNCTION__, mId, crop.left, crop.top, crop.right, crop.bottom); |
| |
| mSourceCrop = crop; |
| return HWC2::Error::None; |
| } |
| |
| hwc_frect_t Layer::getSourceCrop() const { |
| hwc_frect_t crop = mSourceCrop; |
| DEBUG_LOG("%s layer:%" PRIu64 |
| "crop rect-left:%f rect-top:%f rect-right:%f rect-bot:%f", |
| __FUNCTION__, mId, crop.left, crop.top, crop.right, crop.bottom); |
| |
| return crop; |
| } |
| |
| hwc_rect_t Layer::getSourceCropInt() const { |
| hwc_rect_t crop = {}; |
| crop.left = static_cast<int>(mSourceCrop.left); |
| crop.top = static_cast<int>(mSourceCrop.top); |
| crop.right = static_cast<int>(mSourceCrop.right); |
| crop.bottom = static_cast<int>(mSourceCrop.bottom); |
| DEBUG_LOG("%s layer:%" PRIu64 |
| "crop rect-left:%d rect-top:%d rect-right:%d rect-bot:%d", |
| __FUNCTION__, mId, crop.left, crop.top, crop.right, crop.bottom); |
| |
| return crop; |
| } |
| |
| HWC2::Error Layer::setTransform(int32_t transform) { |
| const auto transformType = static_cast<HWC2::Transform>(transform); |
| const auto transformTypeString = to_string(transformType); |
| DEBUG_LOG("%s layer:%" PRIu64 " transform:%s", __FUNCTION__, mId, |
| transformTypeString.c_str()); |
| |
| mTransform = transformType; |
| return HWC2::Error::None; |
| } |
| |
| hwc_transform_t Layer::getTransform() const { |
| const auto transform = mTransform; |
| const auto transformString = to_string(transform); |
| DEBUG_LOG("%s layer:%" PRIu64 " transform:%s", __FUNCTION__, mId, |
| transformString.c_str()); |
| |
| return static_cast<hwc_transform_t>(transform); |
| } |
| |
| HWC2::Error Layer::setVisibleRegion(hwc_region_t visible) { |
| DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId); |
| |
| mVisibleRegion.resize(visible.numRects); |
| std::copy_n(visible.rects, visible.numRects, mVisibleRegion.data()); |
| return HWC2::Error::None; |
| } |
| |
| std::size_t Layer::getNumVisibleRegions() const { |
| std::size_t num = mVisibleRegion.size(); |
| DEBUG_LOG("%s layer:%" PRIu64 " number of visible regions: %zu", __FUNCTION__, |
| mId, num); |
| |
| return num; |
| } |
| |
| HWC2::Error Layer::setZ(uint32_t z) { |
| DEBUG_LOG("%s layer:%" PRIu64 " z:%d", __FUNCTION__, mId, z); |
| |
| mZ = z; |
| return HWC2::Error::None; |
| } |
| |
| uint32_t Layer::getZ() const { |
| uint32_t z = mZ; |
| DEBUG_LOG("%s layer:%" PRIu64 " z:%d", __FUNCTION__, mId, z); |
| |
| return z; |
| } |
| |
| void Layer::logCompositionFallbackIfChanged(HWC2::Composition to) { |
| HWC2::Composition from = getCompositionType(); |
| if (mLastCompositionFallback && mLastCompositionFallback->from == from && |
| mLastCompositionFallback->to == to) { |
| return; |
| } |
| ALOGI("%s: layer %" PRIu32 " CompositionType fallback from %d to %d", __FUNCTION__, |
| static_cast<uint32_t>(getId()), static_cast<int>(from), static_cast<int>(to)); |
| mLastCompositionFallback = { |
| .from = from, |
| .to = to, |
| }; |
| } |
| |
| } // namespace android |