diff options
Diffstat (limited to 'libs/ui')
| -rw-r--r-- | libs/ui/FenceTime.cpp | 8 | ||||
| -rw-r--r-- | libs/ui/Gralloc5.cpp | 225 | ||||
| -rw-r--r-- | libs/ui/GraphicBufferAllocator.cpp | 4 | ||||
| -rw-r--r-- | libs/ui/include/ui/DisplayMap.h | 11 | ||||
| -rw-r--r-- | libs/ui/include/ui/DisplayMode.h | 4 | ||||
| -rw-r--r-- | libs/ui/include/ui/GraphicBuffer.h | 17 | ||||
| -rw-r--r-- | libs/ui/include/ui/ShadowSettings.h | 65 |
7 files changed, 306 insertions, 28 deletions
diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp index 538c1d2a42..4246c40f64 100644 --- a/libs/ui/FenceTime.cpp +++ b/libs/ui/FenceTime.cpp @@ -363,9 +363,9 @@ void FenceToFenceTimeMap::signalAllForTest( } void FenceToFenceTimeMap::garbageCollectLocked() { - for (auto& it : mMap) { + for (auto it = mMap.begin(); it != mMap.end();) { // Erase all expired weak pointers from the vector. - auto& vect = it.second; + auto& vect = it->second; vect.erase( std::remove_if(vect.begin(), vect.end(), [](const std::weak_ptr<FenceTime>& ft) { @@ -375,7 +375,9 @@ void FenceToFenceTimeMap::garbageCollectLocked() { // Also erase the map entry if the vector is now empty. if (vect.empty()) { - mMap.erase(it.first); + it = mMap.erase(it); + } else { + it++; } } } diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp index 123bef4a4f..25850f71cb 100644 --- a/libs/ui/Gralloc5.cpp +++ b/libs/ui/Gralloc5.cpp @@ -31,10 +31,15 @@ using namespace aidl::android::hardware::graphics::allocator; using namespace aidl::android::hardware::graphics::common; using namespace ::android::hardware::graphics::mapper; +using ADataspace = aidl::android::hardware::graphics::common::Dataspace; +using APixelFormat = aidl::android::hardware::graphics::common::PixelFormat; + namespace android { static const auto kIAllocatorServiceName = IAllocator::descriptor + std::string("/default"); static const auto kIAllocatorMinimumVersion = 2; +constexpr const char* kStandardMetadataName = + "android.hardware.graphics.common.StandardMetadataType"; // TODO(b/72323293, b/72703005): Remove these invalid bits from callers static constexpr uint64_t kRemovedUsageBits = static_cast<uint64_t>((1 << 10) | (1 << 13)); @@ -292,17 +297,205 @@ bool Gralloc5Mapper::isLoaded() const { return mMapper != nullptr && mMapper->version >= AIMAPPER_VERSION_5; } +static bool isStandardMetadata(AIMapper_MetadataType metadataType) { + return strcmp(kStandardMetadataName, metadataType.name) == 0; +} + +struct DumpBufferResult { + uint64_t bufferId; + std::string name; + uint64_t width; + uint64_t height; + uint64_t layerCount; + APixelFormat pixelFormatRequested; + uint32_t pixelFormatFourCC; + uint64_t pixelFormatModifier; + BufferUsage usage; + ADataspace dataspace; + uint64_t allocationSize; + uint64_t protectedContent; + ExtendableType compression; + ExtendableType interlaced; + ExtendableType chromaSiting; + std::vector<ui::PlaneLayout> planeLayouts; +}; + +#define DECODE_TO(name, output) \ + case StandardMetadataType::name: \ + output = StandardMetadata<StandardMetadataType::name>::value ::decode(value, valueSize) \ + .value(); \ + break + +static void dumpBufferCommon(DumpBufferResult* outResult, AIMapper_MetadataType metadataType, + const void* value, size_t valueSize) { + if (!isStandardMetadata(metadataType)) { + return; + } + StandardMetadataType type = (StandardMetadataType)metadataType.value; + switch (type) { + DECODE_TO(BUFFER_ID, outResult->bufferId); + DECODE_TO(NAME, outResult->name); + DECODE_TO(WIDTH, outResult->width); + DECODE_TO(HEIGHT, outResult->height); + DECODE_TO(LAYER_COUNT, outResult->layerCount); + DECODE_TO(PIXEL_FORMAT_REQUESTED, outResult->pixelFormatRequested); + DECODE_TO(PIXEL_FORMAT_FOURCC, outResult->pixelFormatFourCC); + DECODE_TO(PIXEL_FORMAT_MODIFIER, outResult->pixelFormatModifier); + DECODE_TO(USAGE, outResult->usage); + DECODE_TO(DATASPACE, outResult->dataspace); + DECODE_TO(ALLOCATION_SIZE, outResult->allocationSize); + DECODE_TO(PROTECTED_CONTENT, outResult->protectedContent); + DECODE_TO(COMPRESSION, outResult->compression); + DECODE_TO(INTERLACED, outResult->interlaced); + DECODE_TO(CHROMA_SITING, outResult->chromaSiting); + DECODE_TO(PLANE_LAYOUTS, outResult->planeLayouts); + default: + break; + } +} + +#undef DECODE_TO + +template <typename EnumT, typename = std::enable_if_t<std::is_enum<EnumT>{}>> +constexpr std::underlying_type_t<EnumT> to_underlying(EnumT e) noexcept { + return static_cast<std::underlying_type_t<EnumT>>(e); +} + +static void writeDumpToStream(const DumpBufferResult& bufferDump, std::ostream& outDump, + bool less) { + double allocationSizeKiB = static_cast<double>(bufferDump.allocationSize) / 1024; + + outDump << "+ name:" << bufferDump.name << ", id:" << bufferDump.bufferId + << ", size:" << std::fixed << allocationSizeKiB << "KiB, w/h:" << bufferDump.width + << "x" << bufferDump.height << ", usage: 0x" << std::hex + << to_underlying(bufferDump.usage) << std::dec + << ", req fmt:" << to_underlying(bufferDump.pixelFormatRequested) + << ", fourcc/mod:" << bufferDump.pixelFormatFourCC << "/" + << bufferDump.pixelFormatModifier << ", dataspace: 0x" << std::hex + << to_underlying(bufferDump.dataspace) << std::dec << ", compressed: "; + + if (less) { + bool isCompressed = !gralloc4::isStandardCompression(bufferDump.compression) || + (gralloc4::getStandardCompressionValue(bufferDump.compression) != + ui::Compression::NONE); + outDump << std::boolalpha << isCompressed << "\n"; + } else { + outDump << gralloc4::getCompressionName(bufferDump.compression) << "\n"; + } + + if (!less) { + bool firstPlane = true; + for (const auto& planeLayout : bufferDump.planeLayouts) { + if (firstPlane) { + firstPlane = false; + outDump << "\tplanes: "; + } else { + outDump << "\t "; + } + + for (size_t i = 0; i < planeLayout.components.size(); i++) { + const auto& planeLayoutComponent = planeLayout.components[i]; + outDump << gralloc4::getPlaneLayoutComponentTypeName(planeLayoutComponent.type); + if (i < planeLayout.components.size() - 1) { + outDump << "/"; + } else { + outDump << ":\t"; + } + } + outDump << " w/h:" << planeLayout.widthInSamples << "x" << planeLayout.heightInSamples + << ", stride:" << planeLayout.strideInBytes + << " bytes, size:" << planeLayout.totalSizeInBytes; + outDump << ", inc:" << planeLayout.sampleIncrementInBits + << " bits, subsampling w/h:" << planeLayout.horizontalSubsampling << "x" + << planeLayout.verticalSubsampling; + outDump << "\n"; + } + + outDump << "\tlayer cnt: " << bufferDump.layerCount + << ", protected content: " << bufferDump.protectedContent + << ", interlaced: " << gralloc4::getInterlacedName(bufferDump.interlaced) + << ", chroma siting:" << gralloc4::getChromaSitingName(bufferDump.chromaSiting) + << "\n"; + } +} + std::string Gralloc5Mapper::dumpBuffer(buffer_handle_t bufferHandle, bool less) const { - // TODO(b/261858392): Implement - (void)bufferHandle; - (void)less; - return {}; + DumpBufferResult bufferInfo; + AIMapper_DumpBufferCallback dumpBuffer = [](void* contextPtr, + AIMapper_MetadataType metadataType, + const void* _Nonnull value, size_t valueSize) { + DumpBufferResult* context = reinterpret_cast<DumpBufferResult*>(contextPtr); + dumpBufferCommon(context, metadataType, value, valueSize); + }; + AIMapper_Error error = mMapper->v5.dumpBuffer(bufferHandle, dumpBuffer, &bufferInfo); + if (error != AIMAPPER_ERROR_NONE) { + ALOGE("Error dumping buffer: %d", error); + return std::string{}; + } + std::ostringstream stream; + stream.precision(2); + writeDumpToStream(bufferInfo, stream, less); + return stream.str(); } std::string Gralloc5Mapper::dumpBuffers(bool less) const { - // TODO(b/261858392): Implement - (void)less; - return {}; + class DumpAllBuffersContext { + private: + bool mHasPending = false; + DumpBufferResult mPending; + std::vector<DumpBufferResult> mResults; + + public: + DumpAllBuffersContext() { mResults.reserve(10); } + + void commit() { + if (mHasPending) { + mResults.push_back(mPending); + mHasPending = false; + } + } + + DumpBufferResult* write() { + mHasPending = true; + return &mPending; + } + + const std::vector<DumpBufferResult>& results() { + commit(); + return mResults; + } + } context; + + AIMapper_BeginDumpBufferCallback beginCallback = [](void* contextPtr) { + DumpAllBuffersContext* context = reinterpret_cast<DumpAllBuffersContext*>(contextPtr); + context->commit(); + }; + + AIMapper_DumpBufferCallback dumpBuffer = [](void* contextPtr, + AIMapper_MetadataType metadataType, + const void* _Nonnull value, size_t valueSize) { + DumpAllBuffersContext* context = reinterpret_cast<DumpAllBuffersContext*>(contextPtr); + dumpBufferCommon(context->write(), metadataType, value, valueSize); + }; + + AIMapper_Error error = mMapper->v5.dumpAllBuffers(beginCallback, dumpBuffer, &context); + if (error != AIMAPPER_ERROR_NONE) { + ALOGE("Error dumping buffers: %d", error); + return std::string{}; + } + uint64_t totalAllocationSize = 0; + std::ostringstream stream; + stream.precision(2); + stream << "Imported gralloc buffers:\n"; + + for (const auto& bufferDump : context.results()) { + writeDumpToStream(bufferDump, stream, less); + totalAllocationSize += bufferDump.allocationSize; + } + + double totalAllocationSizeKiB = static_cast<double>(totalAllocationSize) / 1024; + stream << "Total imported by gralloc: " << totalAllocationSizeKiB << "KiB\n"; + return stream.str(); } status_t Gralloc5Mapper::importBuffer(const native_handle_t *rawHandle, @@ -333,14 +526,16 @@ status_t Gralloc5Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32 } } { - auto value = - getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(mMapper, - bufferHandle); - if (static_cast<::aidl::android::hardware::graphics::common::PixelFormat>(format) != - value) { - ALOGW("Format didn't match, expected %d got %s", format, - value.has_value() ? toString(*value).c_str() : "<null>"); - return BAD_VALUE; + auto expected = static_cast<APixelFormat>(format); + if (expected != APixelFormat::IMPLEMENTATION_DEFINED) { + auto value = + getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(mMapper, + bufferHandle); + if (expected != value) { + ALOGW("Format didn't match, expected %d got %s", format, + value.has_value() ? toString(*value).c_str() : "<null>"); + return BAD_VALUE; + } } } { diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index c0abec23e0..eb0bd4ed0a 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -89,14 +89,14 @@ void GraphicBufferAllocator::dump(std::string& result, bool less) const { uint64_t total = 0; result.append("GraphicBufferAllocator buffers:\n"); const size_t count = list.size(); - StringAppendF(&result, "%10s | %11s | %18s | %s | %8s | %10s | %s\n", "Handle", "Size", + StringAppendF(&result, "%14s | %11s | %18s | %s | %8s | %10s | %s\n", "Handle", "Size", "W (Stride) x H", "Layers", "Format", "Usage", "Requestor"); for (size_t i = 0; i < count; i++) { const alloc_rec_t& rec(list.valueAt(i)); std::string sizeStr = (rec.size) ? base::StringPrintf("%7.2f KiB", static_cast<double>(rec.size) / 1024.0) : "unknown"; - StringAppendF(&result, "%10p | %11s | %4u (%4u) x %4u | %6u | %8X | 0x%8" PRIx64 " | %s\n", + StringAppendF(&result, "%14p | %11s | %4u (%4u) x %4u | %6u | %8X | 0x%8" PRIx64 " | %s\n", list.keyAt(i), sizeStr.c_str(), rec.width, rec.stride, rec.height, rec.layerCount, rec.format, rec.usage, rec.requestorName.c_str()); total += rec.size; diff --git a/libs/ui/include/ui/DisplayMap.h b/libs/ui/include/ui/DisplayMap.h index 7eacb0a7f0..65d2b8fa31 100644 --- a/libs/ui/include/ui/DisplayMap.h +++ b/libs/ui/include/ui/DisplayMap.h @@ -23,13 +23,18 @@ namespace android::ui { // The static capacities were chosen to exceed a typical number of physical and/or virtual displays. +constexpr size_t kDisplayCapacity = 5; template <typename Key, typename Value> -using DisplayMap = ftl::SmallMap<Key, Value, 5>; +using DisplayMap = ftl::SmallMap<Key, Value, kDisplayCapacity>; +constexpr size_t kPhysicalDisplayCapacity = 3; template <typename Key, typename Value> -using PhysicalDisplayMap = ftl::SmallMap<Key, Value, 3>; +using PhysicalDisplayMap = ftl::SmallMap<Key, Value, kPhysicalDisplayCapacity>; template <typename T> -using PhysicalDisplayVector = ftl::SmallVector<T, 3>; +using DisplayVector = ftl::SmallVector<T, kDisplayCapacity>; + +template <typename T> +using PhysicalDisplayVector = ftl::SmallVector<T, kPhysicalDisplayCapacity>; } // namespace android::ui diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h index 65a8769c98..ddb9bbd4bc 100644 --- a/libs/ui/include/ui/DisplayMode.h +++ b/libs/ui/include/ui/DisplayMode.h @@ -37,7 +37,9 @@ struct DisplayMode { float yDpi = 0; std::vector<ui::Hdr> supportedHdrTypes; - float refreshRate = 0; + // Some modes have peak refresh rate lower than the panel vsync rate. + float peakRefreshRate = 0.f; + float vsyncRate = 0.f; nsecs_t appVsyncOffset = 0; nsecs_t sfVsyncOffset = 0; nsecs_t presentationDeadline = 0; diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index dbe475b805..f859848b0c 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -36,6 +36,15 @@ #include <hardware/gralloc.h> +#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__) +// TODO: Provide alternatives that aren't broken +#define AHB_CONVERSION \ + [[deprecated("WARNING: VNDK casts beteween GraphicBuffer & AHardwareBuffer are UNSAFE and " \ + "will be removed in the future")]] +#else +#define AHB_CONVERSION +#endif + namespace android { class GraphicBufferMapper; @@ -80,10 +89,10 @@ public: static sp<GraphicBuffer> from(ANativeWindowBuffer *); - static GraphicBuffer* fromAHardwareBuffer(AHardwareBuffer*); - static GraphicBuffer const* fromAHardwareBuffer(AHardwareBuffer const*); - AHardwareBuffer* toAHardwareBuffer(); - AHardwareBuffer const* toAHardwareBuffer() const; + AHB_CONVERSION static GraphicBuffer* fromAHardwareBuffer(AHardwareBuffer*); + AHB_CONVERSION static GraphicBuffer const* fromAHardwareBuffer(AHardwareBuffer const*); + AHB_CONVERSION AHardwareBuffer* toAHardwareBuffer(); + AHB_CONVERSION AHardwareBuffer const* toAHardwareBuffer() const; // Create a GraphicBuffer to be unflatten'ed into or be reallocated. GraphicBuffer(); diff --git a/libs/ui/include/ui/ShadowSettings.h b/libs/ui/include/ui/ShadowSettings.h new file mode 100644 index 0000000000..c0b83b8691 --- /dev/null +++ b/libs/ui/include/ui/ShadowSettings.h @@ -0,0 +1,65 @@ +/* + * Copyright 2023 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. + */ + +#pragma once + +#include <math/vec4.h> +#include "FloatRect.h" + +namespace android { + +/* + * Contains the configuration for the shadows drawn by single layer. Shadow follows + * material design guidelines. + */ +struct ShadowSettings { + // Boundaries of the shadow. + FloatRect boundaries = FloatRect(); + + // Color to the ambient shadow. The alpha is premultiplied. + vec4 ambientColor = vec4(); + + // Color to the spot shadow. The alpha is premultiplied. The position of the spot shadow + // depends on the light position. + vec4 spotColor = vec4(); + + // Position of the light source used to cast the spot shadow. + vec3 lightPos = vec3(); + + // Radius of the spot light source. Smaller radius will have sharper edges, + // larger radius will have softer shadows + float lightRadius = 0.f; + + // Length of the cast shadow. If length is <= 0.f no shadows will be drawn. + float length = 0.f; + + // If true fill in the casting layer is translucent and the shadow needs to fill the bounds. + // Otherwise the shadow will only be drawn around the edges of the casting layer. + bool casterIsTranslucent = false; +}; + +static inline bool operator==(const ShadowSettings& lhs, const ShadowSettings& rhs) { + return lhs.boundaries == rhs.boundaries && lhs.ambientColor == rhs.ambientColor && + lhs.spotColor == rhs.spotColor && lhs.lightPos == rhs.lightPos && + lhs.lightRadius == rhs.lightRadius && lhs.length == rhs.length && + lhs.casterIsTranslucent == rhs.casterIsTranslucent; +} + +static inline bool operator!=(const ShadowSettings& lhs, const ShadowSettings& rhs) { + return !(operator==(lhs, rhs)); +} + +} // namespace android
\ No newline at end of file |