|  | /* | 
|  | * Copyright 2014 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 <gui/BufferItem.h> | 
|  |  | 
|  | #include <ui/Fence.h> | 
|  | #include <ui/GraphicBuffer.h> | 
|  |  | 
|  | #include <system/window.h> | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | template<typename T> | 
|  | static inline constexpr uint32_t low32(const T n) { | 
|  | return static_cast<uint32_t>(static_cast<uint64_t>(n)); | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | static inline constexpr uint32_t high32(const T n) { | 
|  | return static_cast<uint32_t>(static_cast<uint64_t>(n)>>32); | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | static inline constexpr T to64(const uint32_t lo, const uint32_t hi) { | 
|  | return static_cast<T>(static_cast<uint64_t>(hi)<<32 | lo); | 
|  | } | 
|  |  | 
|  | BufferItem::BufferItem() : | 
|  | mGraphicBuffer(nullptr), | 
|  | mFence(nullptr), | 
|  | mCrop(Rect::INVALID_RECT), | 
|  | mTransform(0), | 
|  | mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), | 
|  | mTimestamp(0), | 
|  | mIsAutoTimestamp(false), | 
|  | mDataSpace(HAL_DATASPACE_UNKNOWN), | 
|  | mFrameNumber(0), | 
|  | mSlot(INVALID_BUFFER_SLOT), | 
|  | mIsDroppable(false), | 
|  | mAcquireCalled(false), | 
|  | mTransformToDisplayInverse(false), | 
|  | mSurfaceDamage(), | 
|  | mAutoRefresh(false), | 
|  | mQueuedBuffer(true), | 
|  | mIsStale(false), | 
|  | mApi(0) { | 
|  | } | 
|  |  | 
|  | BufferItem::~BufferItem() {} | 
|  |  | 
|  | template <typename T> | 
|  | static void addAligned(size_t& size, T /* value */) { | 
|  | size = FlattenableUtils::align<sizeof(T)>(size); | 
|  | size += sizeof(T); | 
|  | } | 
|  |  | 
|  | size_t BufferItem::getPodSize() const { | 
|  | size_t size = 0; | 
|  | addAligned(size, mCrop); | 
|  | addAligned(size, mTransform); | 
|  | addAligned(size, mScalingMode); | 
|  | addAligned(size, low32(mTimestamp)); | 
|  | addAligned(size, high32(mTimestamp)); | 
|  | addAligned(size, mIsAutoTimestamp); | 
|  | addAligned(size, mDataSpace); | 
|  | addAligned(size, low32(mFrameNumber)); | 
|  | addAligned(size, high32(mFrameNumber)); | 
|  | addAligned(size, mSlot); | 
|  | addAligned(size, mIsDroppable); | 
|  | addAligned(size, mAcquireCalled); | 
|  | addAligned(size, mTransformToDisplayInverse); | 
|  | addAligned(size, mAutoRefresh); | 
|  | addAligned(size, mQueuedBuffer); | 
|  | addAligned(size, mIsStale); | 
|  | addAligned(size, mApi); | 
|  | return size; | 
|  | } | 
|  |  | 
|  | size_t BufferItem::getFlattenedSize() const { | 
|  | size_t size = sizeof(uint32_t); // Flags | 
|  | if (mGraphicBuffer != nullptr) { | 
|  | size += mGraphicBuffer->getFlattenedSize(); | 
|  | size = FlattenableUtils::align<4>(size); | 
|  | } | 
|  | if (mFence != nullptr) { | 
|  | size += mFence->getFlattenedSize(); | 
|  | size = FlattenableUtils::align<4>(size); | 
|  | } | 
|  | size += mSurfaceDamage.getFlattenedSize(); | 
|  | size += mHdrMetadata.getFlattenedSize(); | 
|  | size = FlattenableUtils::align<8>(size); | 
|  | return size + getPodSize(); | 
|  | } | 
|  |  | 
|  | size_t BufferItem::getFdCount() const { | 
|  | size_t count = 0; | 
|  | if (mGraphicBuffer != nullptr) { | 
|  | count += mGraphicBuffer->getFdCount(); | 
|  | } | 
|  | if (mFence != nullptr) { | 
|  | count += mFence->getFdCount(); | 
|  | } | 
|  | return count; | 
|  | } | 
|  |  | 
|  | template <typename T> | 
|  | static void writeAligned(void*& buffer, size_t& size, T value) { | 
|  | size -= FlattenableUtils::align<alignof(T)>(buffer); | 
|  | FlattenableUtils::write(buffer, size, value); | 
|  | } | 
|  |  | 
|  | status_t BufferItem::flatten( | 
|  | void*& buffer, size_t& size, int*& fds, size_t& count) const { | 
|  |  | 
|  | // make sure we have enough space | 
|  | if (size < BufferItem::getFlattenedSize()) { | 
|  | return NO_MEMORY; | 
|  | } | 
|  |  | 
|  | // content flags are stored first | 
|  | uint32_t& flags = *static_cast<uint32_t*>(buffer); | 
|  |  | 
|  | // advance the pointer | 
|  | FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); | 
|  |  | 
|  | flags = 0; | 
|  | if (mGraphicBuffer != nullptr) { | 
|  | status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); | 
|  | if (err) return err; | 
|  | size -= FlattenableUtils::align<4>(buffer); | 
|  | flags |= 1; | 
|  | } | 
|  | if (mFence != nullptr) { | 
|  | status_t err = mFence->flatten(buffer, size, fds, count); | 
|  | if (err) return err; | 
|  | size -= FlattenableUtils::align<4>(buffer); | 
|  | flags |= 2; | 
|  | } | 
|  |  | 
|  | status_t err = mSurfaceDamage.flatten(buffer, size); | 
|  | if (err) return err; | 
|  | FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize()); | 
|  |  | 
|  | err = mHdrMetadata.flatten(buffer, size); | 
|  | if (err) return err; | 
|  | FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize()); | 
|  |  | 
|  | // Check we still have enough space | 
|  | if (size < getPodSize()) { | 
|  | return NO_MEMORY; | 
|  | } | 
|  |  | 
|  | writeAligned(buffer, size, mCrop); | 
|  | writeAligned(buffer, size, mTransform); | 
|  | writeAligned(buffer, size, mScalingMode); | 
|  | writeAligned(buffer, size, low32(mTimestamp)); | 
|  | writeAligned(buffer, size, high32(mTimestamp)); | 
|  | writeAligned(buffer, size, mIsAutoTimestamp); | 
|  | writeAligned(buffer, size, mDataSpace); | 
|  | writeAligned(buffer, size, low32(mFrameNumber)); | 
|  | writeAligned(buffer, size, high32(mFrameNumber)); | 
|  | writeAligned(buffer, size, mSlot); | 
|  | writeAligned(buffer, size, mIsDroppable); | 
|  | writeAligned(buffer, size, mAcquireCalled); | 
|  | writeAligned(buffer, size, mTransformToDisplayInverse); | 
|  | writeAligned(buffer, size, mAutoRefresh); | 
|  | writeAligned(buffer, size, mQueuedBuffer); | 
|  | writeAligned(buffer, size, mIsStale); | 
|  | writeAligned(buffer, size, mApi); | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | template <typename T> | 
|  | static void readAligned(const void*& buffer, size_t& size, T& value) { | 
|  | size -= FlattenableUtils::align<alignof(T)>(buffer); | 
|  | FlattenableUtils::read(buffer, size, value); | 
|  | } | 
|  |  | 
|  | status_t BufferItem::unflatten( | 
|  | void const*& buffer, size_t& size, int const*& fds, size_t& count) { | 
|  |  | 
|  | if (size < sizeof(uint32_t)) { | 
|  | return NO_MEMORY; | 
|  | } | 
|  |  | 
|  | uint32_t flags = 0; | 
|  | FlattenableUtils::read(buffer, size, flags); | 
|  |  | 
|  | if (flags & 1) { | 
|  | mGraphicBuffer = new GraphicBuffer(); | 
|  | status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); | 
|  | if (err) return err; | 
|  | size -= FlattenableUtils::align<4>(buffer); | 
|  | } | 
|  |  | 
|  | if (flags & 2) { | 
|  | mFence = new Fence(); | 
|  | status_t err = mFence->unflatten(buffer, size, fds, count); | 
|  | if (err) return err; | 
|  | size -= FlattenableUtils::align<4>(buffer); | 
|  |  | 
|  | mFenceTime = std::make_shared<FenceTime>(mFence); | 
|  | } | 
|  |  | 
|  | status_t err = mSurfaceDamage.unflatten(buffer, size); | 
|  | if (err) return err; | 
|  | FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize()); | 
|  |  | 
|  | err = mHdrMetadata.unflatten(buffer, size); | 
|  | if (err) return err; | 
|  | FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize()); | 
|  |  | 
|  | // Check we still have enough space | 
|  | if (size < getPodSize()) { | 
|  | return NO_MEMORY; | 
|  | } | 
|  |  | 
|  | uint32_t timestampLo = 0, timestampHi = 0; | 
|  | uint32_t frameNumberLo = 0, frameNumberHi = 0; | 
|  |  | 
|  | readAligned(buffer, size, mCrop); | 
|  | readAligned(buffer, size, mTransform); | 
|  | readAligned(buffer, size, mScalingMode); | 
|  | readAligned(buffer, size, timestampLo); | 
|  | readAligned(buffer, size, timestampHi); | 
|  | mTimestamp = to64<int64_t>(timestampLo, timestampHi); | 
|  | readAligned(buffer, size, mIsAutoTimestamp); | 
|  | readAligned(buffer, size, mDataSpace); | 
|  | readAligned(buffer, size, frameNumberLo); | 
|  | readAligned(buffer, size, frameNumberHi); | 
|  | mFrameNumber = to64<uint64_t>(frameNumberLo, frameNumberHi); | 
|  | readAligned(buffer, size, mSlot); | 
|  | readAligned(buffer, size, mIsDroppable); | 
|  | readAligned(buffer, size, mAcquireCalled); | 
|  | readAligned(buffer, size, mTransformToDisplayInverse); | 
|  | readAligned(buffer, size, mAutoRefresh); | 
|  | readAligned(buffer, size, mQueuedBuffer); | 
|  | readAligned(buffer, size, mIsStale); | 
|  | readAligned(buffer, size, mApi); | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | const char* BufferItem::scalingModeName(uint32_t scalingMode) { | 
|  | switch (scalingMode) { | 
|  | case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE"; | 
|  | case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW"; | 
|  | case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP"; | 
|  | default: return "Unknown"; | 
|  | } | 
|  | } | 
|  |  | 
|  | } // namespace android |