summaryrefslogtreecommitdiff
path: root/libs/ui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ui')
-rw-r--r--libs/ui/FenceTime.cpp8
-rw-r--r--libs/ui/Gralloc5.cpp225
-rw-r--r--libs/ui/GraphicBufferAllocator.cpp4
-rw-r--r--libs/ui/include/ui/DisplayMap.h11
-rw-r--r--libs/ui/include/ui/DisplayMode.h4
-rw-r--r--libs/ui/include/ui/GraphicBuffer.h17
-rw-r--r--libs/ui/include/ui/ShadowSettings.h65
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