From 77565571fc884e74cdf7a7b9ed0cbf37a70b6747 Mon Sep 17 00:00:00 2001 From: Jiwen 'Steve' Cai Date: Mon, 15 Oct 2018 11:31:29 -0700 Subject: Remove DetachedBufferHandle from libui DetachedBufferHandle was a temporary measure introduced in Android P to bridge BufferHub and GraphicBuffer. In Android Q however, GraphicBuffer will be directly backed by BufferHub, thus DetachedBufferHandle becomes redundant. Also note that removing DetachedBufferHandle from libui should bare no impact on vendors for two reasons: 1. BufferHub in P is only enabled for Daydream ready devices (i.e. Pixel lines and VR AIO devices). No other vendors should have BufferHub enabled. 2. DetachedBufferHandle.h was hidden from vndk and thus vendors shouldn't get access to it anyway. Bug: 117522732 Test: Build system Change-Id: I3828eaa9499051e5ad5e4e270b5c26bae5f2c707 --- libs/ui/GraphicBuffer.cpp | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index c50d1d038e..5a1ddee002 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -22,7 +22,6 @@ #include -#include #include #include #include @@ -490,24 +489,6 @@ status_t GraphicBuffer::unflatten( return NO_ERROR; } -bool GraphicBuffer::isDetachedBuffer() const { - return mDetachedBufferHandle && mDetachedBufferHandle->isValid(); -} - -status_t GraphicBuffer::setDetachedBufferHandle(std::unique_ptr channel) { - if (isDetachedBuffer()) { - ALOGW("setDetachedBuffer: there is already a BufferHub channel associated with this " - "GraphicBuffer. Replacing the old one."); - } - - mDetachedBufferHandle = std::move(channel); - return NO_ERROR; -} - -std::unique_ptr GraphicBuffer::takeDetachedBufferHandle() { - return std::move(mDetachedBufferHandle); -} - // --------------------------------------------------------------------------- }; // namespace android -- cgit v1.2.3-59-g8ed1b From 2daf5189a8f9c28a804a550f3734c5617bac17aa Mon Sep 17 00:00:00 2001 From: Jiwen 'Steve' Cai Date: Tue, 16 Oct 2018 00:14:03 -0700 Subject: Create GraphicBuffer backed by BufferHubBuffer The newly created GraphicBuffer shall own the BufferHubBuffer object through out its life cycle. Bug: 70912269 Bug: 111976433 Test: GraphicBuffer_test Change-Id: I698573e26f85dd40d30c267aeea545e65a7e2a8b --- libs/ui/Android.bp | 4 +++ libs/ui/BufferHubBuffer.cpp | 10 +++++++ libs/ui/GraphicBuffer.cpp | 25 +++++++++++++++++ libs/ui/include/ui/BufferHubBuffer.h | 13 +++++++-- libs/ui/include/ui/GraphicBuffer.h | 19 +++++++++++++ libs/ui/tests/Android.bp | 16 +++++++++++ libs/ui/tests/GraphicBuffer_test.cpp | 54 ++++++++++++++++++++++++++++++++++++ 7 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 libs/ui/tests/GraphicBuffer_test.cpp (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 0a0c8ca014..f7709754c8 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -109,6 +109,7 @@ cc_library_shared { // bufferhub is not used when building libgui for vendors target: { vendor: { + cflags: ["-DLIBUI_IN_VNDK"], exclude_srcs: [ "BufferHubBuffer.cpp", "BufferHubMetadata.cpp", @@ -116,6 +117,7 @@ cc_library_shared { exclude_header_libs: [ "libbufferhub_headers", "libdvr_headers", + "libnativewindow_headers", ], exclude_shared_libs: [ "libpdx_default_transport", @@ -128,6 +130,7 @@ cc_library_shared { "libbufferhub_headers", "libdvr_headers", "libnativebase_headers", + "libnativewindow_headers", "libhardware_headers", "libui_headers", "libpdx_headers", @@ -155,6 +158,7 @@ cc_library_headers { vendor_available: true, target: { vendor: { + cflags: ["-DLIBUI_IN_VNDK"], override_export_include_dirs: ["include_vndk"], }, }, diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp index dd79775d01..e747ee11be 100644 --- a/libs/ui/BufferHubBuffer.cpp +++ b/libs/ui/BufferHubBuffer.cpp @@ -160,6 +160,16 @@ int BufferHubBuffer::ImportGraphicBuffer() { // GraphicBuffer instance can be created in future. mBufferHandle = bufferTraits.take_buffer_handle(); + // Populate buffer desc based on buffer traits. + mBufferDesc.width = bufferTraits.width(); + mBufferDesc.height = bufferTraits.height(); + mBufferDesc.layers = bufferTraits.layer_count(); + mBufferDesc.format = bufferTraits.format(); + mBufferDesc.usage = bufferTraits.usage(); + mBufferDesc.stride = bufferTraits.stride(); + mBufferDesc.rfu0 = 0U; + mBufferDesc.rfu1 = 0U; + // If all imports succeed, replace the previous buffer and id. mId = bufferId; mClientStateMask = bufferTraits.client_state_mask(); diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 29deb010e8..e606e26f8b 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -22,6 +22,10 @@ #include +#ifndef LIBUI_IN_VNDK +#include +#endif // LIBUI_IN_VNDK + #include #include #include @@ -89,6 +93,21 @@ GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod m inUsage, inStride); } +#ifndef LIBUI_IN_VNDK +GraphicBuffer::GraphicBuffer(std::unique_ptr buffer) : GraphicBuffer() { + if (buffer == nullptr) { + mInitCheck = BAD_VALUE; + return; + } + + mInitCheck = initWithHandle(buffer->DuplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE, + buffer->desc().width, buffer->desc().height, + static_cast(buffer->desc().format), + buffer->desc().layers, buffer->desc().usage, buffer->desc().stride); + mBufferHubBuffer = std::move(buffer); +} +#endif // LIBUI_IN_VNDK + GraphicBuffer::~GraphicBuffer() { if (handle) { @@ -483,6 +502,12 @@ status_t GraphicBuffer::unflatten( return NO_ERROR; } +#ifndef LIBUI_IN_VNDK +bool GraphicBuffer::isBufferHubBuffer() const { + return mBufferHubBuffer != nullptr; +} +#endif // LIBUI_IN_VNDK + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h index daf61928a4..6850b43f8a 100644 --- a/libs/ui/include/ui/BufferHubBuffer.h +++ b/libs/ui/include/ui/BufferHubBuffer.h @@ -38,6 +38,7 @@ #include #pragma clang diagnostic pop +#include #include namespace android { @@ -62,9 +63,9 @@ public: // Allocates a standalone BufferHubBuffer not associated with any producer consumer set. static std::unique_ptr Create(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, - uint64_t usage, size_t mUserMetadataSize) { + uint64_t usage, size_t userMetadataSize) { return std::unique_ptr( - new BufferHubBuffer(width, height, layerCount, format, usage, mUserMetadataSize)); + new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize)); } // Imports the given channel handle to a BufferHubBuffer, taking ownership. @@ -79,6 +80,9 @@ public: // bufferhubd share the same buffer id. int id() const { return mId; } + // Returns the buffer description, which is guaranteed to be faithful values from bufferhubd. + const AHardwareBuffer_Desc& desc() const { return mBufferDesc; } + const native_handle_t* DuplicateHandle() { return mBufferHandle.DuplicateHandle(); } // Returns the current value of MetadataHeader::buffer_state. @@ -118,7 +122,7 @@ public: private: BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, - uint64_t usage, size_t mUserMetadataSize); + uint64_t usage, size_t userMetadataSize); BufferHubBuffer(pdx::LocalChannelHandle mChannelHandle); @@ -128,6 +132,9 @@ private: int mId = -1; uint64_t mClientStateMask = 0; + // Stores ground truth of the buffer. + AHardwareBuffer_Desc mBufferDesc; + // Wrapps the gralloc buffer handle of this buffer. dvr::NativeHandleWrapper mBufferHandle; diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index fe6229ab48..81f6cd9061 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -34,6 +34,10 @@ namespace android { +#ifndef LIBUI_IN_VNDK +class BufferHubBuffer; +#endif // LIBUI_IN_VNDK + class GraphicBufferMapper; // =========================================================================== @@ -133,6 +137,11 @@ public: GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inUsage, std::string requestorName = ""); +#ifndef LIBUI_IN_VNDK + // Create a GraphicBuffer from an existing BufferHubBuffer. + GraphicBuffer(std::unique_ptr buffer); +#endif // LIBUI_IN_VNDK + // return status status_t initCheck() const; @@ -188,6 +197,11 @@ public: status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); +#ifndef LIBUI_IN_VNDK + // Returns whether this GraphicBuffer is backed by BufferHubBuffer. + bool isBufferHubBuffer() const; +#endif // LIBUI_IN_VNDK + private: ~GraphicBuffer(); @@ -237,6 +251,11 @@ private: // match the BufferQueue's internal generation number (set through // IGBP::setGenerationNumber), attempts to attach the buffer will fail. uint32_t mGenerationNumber; + +#ifndef LIBUI_IN_VNDK + // Stores a BufferHubBuffer that handles buffer signaling, identification. + std::unique_ptr mBufferHubBuffer; +#endif // LIBUI_IN_VNDK }; }; // namespace android diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 4c9c1768e0..b7ad4e5a80 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -28,6 +28,22 @@ cc_test { cflags: ["-Wall", "-Werror"], } +cc_test { + name: "GraphicBuffer_test", + header_libs: [ + "libbufferhub_headers", + "libdvr_headers", + "libnativewindow_headers", + ], + shared_libs: [ + "libpdx_default_transport", + "libui", + "libutils", + ], + srcs: ["GraphicBuffer_test.cpp"], + cflags: ["-Wall", "-Werror"], +} + cc_test { name: "BufferHubBuffer_test", header_libs: [ diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp new file mode 100644 index 0000000000..95ca2c16b3 --- /dev/null +++ b/libs/ui/tests/GraphicBuffer_test.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2018 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. + */ + +#define LOG_TAG "GraphicBufferTest" + +#include +#include + +#include + +namespace android { + +namespace { + +constexpr uint32_t kTestWidth = 1024; +constexpr uint32_t kTestHeight = 1; +constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB; +constexpr uint32_t kTestLayerCount = 1; +constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN; + +} // namespace + +class GraphicBufferTest : public testing::Test {}; + +TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) { + std::unique_ptr b1 = + BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, + kTestUsage, /*userMetadataSize=*/0); + EXPECT_TRUE(b1->IsValid()); + + sp gb(new GraphicBuffer(std::move(b1))); + EXPECT_TRUE(gb->isBufferHubBuffer()); + + EXPECT_EQ(gb->getWidth(), kTestWidth); + EXPECT_EQ(gb->getHeight(), kTestHeight); + EXPECT_EQ(static_cast(gb->getPixelFormat()), kTestFormat); + EXPECT_EQ(gb->getUsage(), kTestUsage); + EXPECT_EQ(gb->getLayerCount(), kTestLayerCount); +} + +} // namespace android -- cgit v1.2.3-59-g8ed1b From 29160fb83353746a5177ccbd663bd17d6747d8b1 Mon Sep 17 00:00:00 2001 From: Jiwen 'Steve' Cai Date: Thu, 13 Dec 2018 12:03:28 -0800 Subject: Expose mBufferId for GraphicBuffer Bug: 118844974 Test: GraphicBuffer_test Change-Id: I75a58b21e9943ffed9219a37e0d05c6697232bf4 --- libs/ui/GraphicBuffer.cpp | 1 + libs/ui/include/ui/GraphicBuffer.h | 7 +++++++ libs/ui/tests/GraphicBuffer_test.cpp | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index e606e26f8b..f408fcbe84 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -104,6 +104,7 @@ GraphicBuffer::GraphicBuffer(std::unique_ptr buffer) : GraphicB buffer->desc().width, buffer->desc().height, static_cast(buffer->desc().format), buffer->desc().layers, buffer->desc().usage, buffer->desc().stride); + mBufferId = buffer->id(); mBufferHubBuffer = std::move(buffer); } #endif // LIBUI_IN_VNDK diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 81f6cd9061..b73ca2b793 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -153,6 +153,7 @@ public: uint32_t getLayerCount() const { return static_cast(layerCount); } Rect getBounds() const { return Rect(width, height); } uint64_t getId() const { return mId; } + int32_t getBufferId() const { return mBufferId; } uint32_t getGenerationNumber() const { return mGenerationNumber; } void setGenerationNumber(uint32_t generation) { @@ -247,6 +248,12 @@ private: uint64_t mId; + // System unique buffer ID. Note that this is different from mId, which is process unique. For + // GraphicBuffer backed by BufferHub, the mBufferId is a system unique identifier that stays the + // same cross process for the same chunck of underlying memory. Also note that this only applies + // to GraphicBuffers that are backed by BufferHub. + int32_t mBufferId = -1; + // Stores the generation number of this buffer. If this number does not // match the BufferQueue's internal generation number (set through // IGBP::setGenerationNumber), attempts to attach the buffer will fail. diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp index 95ca2c16b3..81ab3acfe4 100644 --- a/libs/ui/tests/GraphicBuffer_test.cpp +++ b/libs/ui/tests/GraphicBuffer_test.cpp @@ -39,6 +39,7 @@ TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) { std::unique_ptr b1 = BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, kTestUsage, /*userMetadataSize=*/0); + EXPECT_NE(b1, nullptr); EXPECT_TRUE(b1->IsValid()); sp gb(new GraphicBuffer(std::move(b1))); @@ -51,4 +52,26 @@ TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) { EXPECT_EQ(gb->getLayerCount(), kTestLayerCount); } +TEST_F(GraphicBufferTest, InvalidBufferIdForNoneBufferHubBuffer) { + sp gb( + new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount, kTestUsage)); + EXPECT_FALSE(gb->isBufferHubBuffer()); + EXPECT_EQ(gb->getBufferId(), -1); +} + +TEST_F(GraphicBufferTest, BufferIdMatchesBufferHubBufferId) { + std::unique_ptr b1 = + BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, + kTestUsage, /*userMetadataSize=*/0); + EXPECT_NE(b1, nullptr); + EXPECT_TRUE(b1->IsValid()); + + int b1_id = b1->id(); + EXPECT_GE(b1_id, 0); + + sp gb(new GraphicBuffer(std::move(b1))); + EXPECT_TRUE(gb->isBufferHubBuffer()); + EXPECT_EQ(gb->getBufferId(), b1_id); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From 0c9fc361b466e3ac66d362b23d71ab7ba9b9ca96 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 22 Jan 2019 09:17:19 -0800 Subject: Modifying Gralloc to handle bytesPerPixel and bytesPerStride Bug: 120493579 Test: build, boot Change-Id: I1fe5acc17389db6d57529d2e120ab6e1f3715705 --- libs/ui/Gralloc2.cpp | 9 ++++++++- libs/ui/Gralloc3.cpp | 12 ++++++++++-- libs/ui/GraphicBuffer.cpp | 11 ++++++++--- libs/ui/GraphicBufferMapper.cpp | 28 +++++++++++++++------------- libs/ui/include/ui/Gralloc.h | 3 ++- libs/ui/include/ui/Gralloc2.h | 3 ++- libs/ui/include/ui/Gralloc3.h | 3 ++- libs/ui/include/ui/GraphicBufferMapper.h | 15 ++++++++------- 8 files changed, 55 insertions(+), 29 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp index ea7321e24c..2c4b5f32b1 100644 --- a/libs/ui/Gralloc2.cpp +++ b/libs/ui/Gralloc2.cpp @@ -227,7 +227,14 @@ void Gralloc2Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* ou } status_t Gralloc2Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds, - int acquireFence, void** outData) const { + int acquireFence, void** outData, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) const { + if (outBytesPerPixel) { + *outBytesPerPixel = -1; + } + if (outBytesPerStride) { + *outBytesPerStride = -1; + } auto buffer = const_cast(bufferHandle); IMapper::Rect accessRegion = sGralloc2Rect(bounds); diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp index 128200e33e..acb6b01188 100644 --- a/libs/ui/Gralloc3.cpp +++ b/libs/ui/Gralloc3.cpp @@ -192,7 +192,8 @@ void Gralloc3Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* ou } status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds, - int acquireFence, void** outData) const { + int acquireFence, void** outData, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) const { auto buffer = const_cast(bufferHandle); IMapper::Rect accessRegion = sGralloc3Rect(bounds); @@ -208,12 +209,19 @@ status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, cons Error error; auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle, - [&](const auto& tmpError, const auto& tmpData) { + [&](const auto& tmpError, const auto& tmpData, + const auto& tmpBytesPerPixel, const auto& tmpBytesPerStride) { error = tmpError; if (error != Error::NONE) { return; } *outData = tmpData; + if (outBytesPerPixel) { + *outBytesPerPixel = tmpBytesPerPixel; + } + if (outBytesPerStride) { + *outBytesPerStride = tmpBytesPerStride; + } }); // we own acquireFence even on errors diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index f408fcbe84..da24cf1c06 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -252,7 +252,10 @@ status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) width, height); return BAD_VALUE; } - status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr); + int32_t bytesPerPixel, bytesPerStride; + + status_t res = + getBufferMapper().lock(handle, inUsage, rect, vaddr, &bytesPerPixel, &bytesPerStride); return res; } @@ -306,8 +309,10 @@ status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, width, height); return BAD_VALUE; } - status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, - inConsumerUsage, rect, vaddr, fenceFd); + + int32_t bytesPerPixel, bytesPerStride; + status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, inConsumerUsage, rect, + vaddr, fenceFd, &bytesPerPixel, &bytesPerStride); return res; } diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index b04932938c..9e36377c3d 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -102,10 +102,10 @@ status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle) return NO_ERROR; } -status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage, - const Rect& bounds, void** vaddr) -{ - return lockAsync(handle, usage, bounds, vaddr, -1); +status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds, + void** vaddr, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) { + return lockAsync(handle, usage, bounds, vaddr, -1, outBytesPerPixel, outBytesPerStride); } status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage, @@ -125,21 +125,23 @@ status_t GraphicBufferMapper::unlock(buffer_handle_t handle) return error; } -status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, - uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd) -{ - return lockAsync(handle, usage, usage, bounds, vaddr, fenceFd); +status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds, + void** vaddr, int fenceFd, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) { + return lockAsync(handle, usage, usage, bounds, vaddr, fenceFd, outBytesPerPixel, + outBytesPerStride); } -status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, - uint64_t producerUsage, uint64_t consumerUsage, const Rect& bounds, - void** vaddr, int fenceFd) -{ +status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint64_t producerUsage, + uint64_t consumerUsage, const Rect& bounds, void** vaddr, + int fenceFd, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) { ATRACE_CALL(); const uint64_t usage = static_cast( android_convertGralloc1To0Usage(producerUsage, consumerUsage)); - return mMapper->lock(handle, usage, bounds, fenceFd, vaddr); + return mMapper->lock(handle, usage, bounds, fenceFd, vaddr, outBytesPerPixel, + outBytesPerStride); } status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle, diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h index 92bf043064..a484bce4df 100644 --- a/libs/ui/include/ui/Gralloc.h +++ b/libs/ui/include/ui/Gralloc.h @@ -56,7 +56,8 @@ public: // The ownership of acquireFence is always transferred to the callee, even // on errors. virtual status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds, - int acquireFence, void** outData) const = 0; + int acquireFence, void** outData, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) const = 0; // The ownership of acquireFence is always transferred to the callee, even // on errors. diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h index e03cb4357c..b23d8f77e4 100644 --- a/libs/ui/include/ui/Gralloc2.h +++ b/libs/ui/include/ui/Gralloc2.h @@ -53,7 +53,8 @@ public: uint32_t* outNumInts) const override; status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds, - int acquireFence, void** outData) const override; + int acquireFence, void** outData, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) const override; status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds, int acquireFence, android_ycbcr* ycbcr) const override; diff --git a/libs/ui/include/ui/Gralloc3.h b/libs/ui/include/ui/Gralloc3.h index 510ce4ac23..b0cbcc1300 100644 --- a/libs/ui/include/ui/Gralloc3.h +++ b/libs/ui/include/ui/Gralloc3.h @@ -52,7 +52,8 @@ public: uint32_t* outNumInts) const override; status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds, - int acquireFence, void** outData) const override; + int acquireFence, void** outData, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) const override; status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds, int acquireFence, android_ycbcr* ycbcr) const override; diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h index 156bd7abcd..072926ff44 100644 --- a/libs/ui/include/ui/GraphicBufferMapper.h +++ b/libs/ui/include/ui/GraphicBufferMapper.h @@ -56,20 +56,21 @@ public: void getTransportSize(buffer_handle_t handle, uint32_t* outTransportNumFds, uint32_t* outTransportNumInts); - status_t lock(buffer_handle_t handle, - uint32_t usage, const Rect& bounds, void** vaddr); + status_t lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr, + int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr); status_t lockYCbCr(buffer_handle_t handle, uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr); status_t unlock(buffer_handle_t handle); - status_t lockAsync(buffer_handle_t handle, - uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd); + status_t lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr, + int fenceFd, int32_t* outBytesPerPixel = nullptr, + int32_t* outBytesPerStride = nullptr); - status_t lockAsync(buffer_handle_t handle, - uint64_t producerUsage, uint64_t consumerUsage, const Rect& bounds, - void** vaddr, int fenceFd); + status_t lockAsync(buffer_handle_t handle, uint64_t producerUsage, uint64_t consumerUsage, + const Rect& bounds, void** vaddr, int fenceFd, + int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr); status_t lockAsyncYCbCr(buffer_handle_t handle, uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, -- cgit v1.2.3-59-g8ed1b From 250c654efecb084f5da8157eae2e210a4eddf19f Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Thu, 31 Jan 2019 14:23:43 -0800 Subject: Adding optional 3.0 lock support to GraphicBuffer Adding optional 3.0 lock parameters to GraphicBuffer Modifying isSupported to isLoaded Bug: 123423521 Test: build, boot Change-Id: If4a92bd7916072c2cd7005ca6f332f4a90098d27 --- libs/ui/Gralloc2.cpp | 4 ++-- libs/ui/Gralloc3.cpp | 4 ++-- libs/ui/GraphicBuffer.cpp | 16 ++++++++-------- libs/ui/GraphicBufferAllocator.cpp | 4 ++-- libs/ui/GraphicBufferMapper.cpp | 4 ++-- libs/ui/include/ui/Gralloc.h | 4 ++-- libs/ui/include/ui/Gralloc2.h | 4 ++-- libs/ui/include/ui/Gralloc3.h | 4 ++-- libs/ui/include/ui/GraphicBuffer.h | 8 ++++++-- 9 files changed, 28 insertions(+), 24 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp index 2c4b5f32b1..92ea07cbc4 100644 --- a/libs/ui/Gralloc2.cpp +++ b/libs/ui/Gralloc2.cpp @@ -94,7 +94,7 @@ Gralloc2Mapper::Gralloc2Mapper() { mMapperV2_1 = IMapper::castFrom(mMapper); } -bool Gralloc2Mapper::isSupported() const { +bool Gralloc2Mapper::isLoaded() const { return mMapper != nullptr; } @@ -359,7 +359,7 @@ Gralloc2Allocator::Gralloc2Allocator(const Gralloc2Mapper& mapper) : mMapper(map } } -bool Gralloc2Allocator::isSupported() const { +bool Gralloc2Allocator::isLoaded() const { return mAllocator != nullptr; } diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp index acb6b01188..306a74b80c 100644 --- a/libs/ui/Gralloc3.cpp +++ b/libs/ui/Gralloc3.cpp @@ -92,7 +92,7 @@ Gralloc3Mapper::Gralloc3Mapper() { } } -bool Gralloc3Mapper::isSupported() const { +bool Gralloc3Mapper::isLoaded() const { return mMapper != nullptr; } @@ -322,7 +322,7 @@ Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(map } } -bool Gralloc3Allocator::isSupported() const { +bool Gralloc3Allocator::isLoaded() const { return mAllocator != nullptr; } diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index da24cf1c06..15597eb666 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -236,15 +236,15 @@ status_t GraphicBuffer::initWithHandle(const native_handle_t* inHandle, HandleWr return NO_ERROR; } -status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr) -{ +status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel, + int32_t* outBytesPerStride) { const Rect lockBounds(width, height); - status_t res = lock(inUsage, lockBounds, vaddr); + status_t res = lock(inUsage, lockBounds, vaddr, outBytesPerPixel, outBytesPerStride); return res; } -status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) -{ +status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr, + int32_t* outBytesPerPixel, int32_t* outBytesPerStride) { if (rect.left < 0 || rect.right > width || rect.top < 0 || rect.bottom > height) { ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", @@ -252,10 +252,10 @@ status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr) width, height); return BAD_VALUE; } - int32_t bytesPerPixel, bytesPerStride; - status_t res = - getBufferMapper().lock(handle, inUsage, rect, vaddr, &bytesPerPixel, &bytesPerStride); + status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr, outBytesPerPixel, + outBytesPerStride); + return res; } diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index efb5798167..5a67dc4a4d 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -48,12 +48,12 @@ KeyedVector( reinterpret_cast(mMapper.getGrallocMapper())); - if (!mAllocator->isSupported()) { + if (!mAllocator->isLoaded()) { mAllocator = std::make_unique( reinterpret_cast(mMapper.getGrallocMapper())); } - if (!mAllocator->isSupported()) { + if (!mAllocator->isLoaded()) { LOG_ALWAYS_FATAL("gralloc-allocator is missing"); } } diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index 9e36377c3d..79c333fce4 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -51,11 +51,11 @@ void GraphicBufferMapper::preloadHal() { GraphicBufferMapper::GraphicBufferMapper() { mMapper = std::make_unique(); - if (!mMapper->isSupported()) { + if (!mMapper->isLoaded()) { mMapper = std::make_unique(); } - if (!mMapper->isSupported()) { + if (!mMapper->isLoaded()) { LOG_ALWAYS_FATAL("gralloc-mapper is missing"); } } diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h index a484bce4df..1b8a930c4c 100644 --- a/libs/ui/include/ui/Gralloc.h +++ b/libs/ui/include/ui/Gralloc.h @@ -31,7 +31,7 @@ class GrallocMapper { public: virtual ~GrallocMapper(); - virtual bool isSupported() const = 0; + virtual bool isLoaded() const = 0; virtual status_t createDescriptor(void* bufferDescriptorInfo, void* outBufferDescriptor) const = 0; @@ -74,7 +74,7 @@ class GrallocAllocator { public: virtual ~GrallocAllocator(); - virtual bool isSupported() const = 0; + virtual bool isLoaded() const = 0; virtual std::string dumpDebugInfo() const = 0; diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h index b23d8f77e4..4ef9b51e4f 100644 --- a/libs/ui/include/ui/Gralloc2.h +++ b/libs/ui/include/ui/Gralloc2.h @@ -36,7 +36,7 @@ public: Gralloc2Mapper(); - bool isSupported() const override; + bool isLoaded() const override; status_t createDescriptor(void* bufferDescriptorInfo, void* outBufferDescriptor) const override; @@ -76,7 +76,7 @@ public: // time. Gralloc2Allocator(const Gralloc2Mapper& mapper); - bool isSupported() const override; + bool isLoaded() const override; std::string dumpDebugInfo() const override; diff --git a/libs/ui/include/ui/Gralloc3.h b/libs/ui/include/ui/Gralloc3.h index b0cbcc1300..879e96ed40 100644 --- a/libs/ui/include/ui/Gralloc3.h +++ b/libs/ui/include/ui/Gralloc3.h @@ -35,7 +35,7 @@ public: Gralloc3Mapper(); - bool isSupported() const override; + bool isLoaded() const override; status_t createDescriptor(void* bufferDescriptorInfo, void* outBufferDescriptor) const override; @@ -74,7 +74,7 @@ public: // time. Gralloc3Allocator(const Gralloc3Mapper& mapper); - bool isSupported() const override; + bool isLoaded() const override; std::string dumpDebugInfo() const override; diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index b73ca2b793..18a27a01dd 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -169,8 +169,12 @@ public: bool needsReallocation(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage); - status_t lock(uint32_t inUsage, void** vaddr); - status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr); + // For the following two lock functions, if bytesPerStride or bytesPerPixel + // are unknown or variable, -1 will be returned + status_t lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel = nullptr, + int32_t* outBytesPerStride = nullptr); + status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr, + int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr); // For HAL_PIXEL_FORMAT_YCbCr_420_888 status_t lockYCbCr(uint32_t inUsage, android_ycbcr *ycbcr); status_t lockYCbCr(uint32_t inUsage, const Rect& rect, -- cgit v1.2.3-59-g8ed1b From ddbfaeb7a6b67e93f7a2519c7725561de644d671 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Fri, 1 Feb 2019 09:54:20 -0800 Subject: Adding isSupported HIDL Mapper function support to framework Bug: 123423521 Test: build, boot, manual testing Change-Id: Iee52de6f5610a8465b1f4435d02dc61a8064064a --- libs/ui/Gralloc2.cpp | 6 ++++++ libs/ui/Gralloc3.cpp | 30 ++++++++++++++++++++++++++++++ libs/ui/GraphicBuffer.cpp | 7 +++++++ libs/ui/GraphicBufferMapper.cpp | 5 +++++ libs/ui/include/ui/Gralloc.h | 9 +++++++++ libs/ui/include/ui/Gralloc2.h | 3 +++ libs/ui/include/ui/Gralloc3.h | 3 +++ libs/ui/include/ui/GraphicBuffer.h | 3 +++ libs/ui/include/ui/GraphicBufferMapper.h | 3 +++ 9 files changed, 69 insertions(+) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp index 92ea07cbc4..5dc453005d 100644 --- a/libs/ui/Gralloc2.cpp +++ b/libs/ui/Gralloc2.cpp @@ -351,6 +351,12 @@ int Gralloc2Mapper::unlock(buffer_handle_t bufferHandle) const { return releaseFence; } +status_t Gralloc2Mapper::isSupported(uint32_t /*width*/, uint32_t /*height*/, + android::PixelFormat /*format*/, uint32_t /*layerCount*/, + uint64_t /*usage*/, bool* /*outSupported*/) const { + return INVALID_OPERATION; +} + Gralloc2Allocator::Gralloc2Allocator(const Gralloc2Mapper& mapper) : mMapper(mapper) { mAllocator = IAllocator::getService(); if (mAllocator == nullptr) { diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp index 306a74b80c..7f8e57c9cb 100644 --- a/libs/ui/Gralloc3.cpp +++ b/libs/ui/Gralloc3.cpp @@ -314,6 +314,36 @@ int Gralloc3Mapper::unlock(buffer_handle_t bufferHandle) const { return releaseFence; } +status_t Gralloc3Mapper::isSupported(uint32_t width, uint32_t height, android::PixelFormat format, + uint32_t layerCount, uint64_t usage, + bool* outSupported) const { + IMapper::BufferDescriptorInfo descriptorInfo; + sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo); + + Error error; + auto ret = mMapper->isSupported(descriptorInfo, + [&](const auto& tmpError, const auto& tmpSupported) { + error = tmpError; + if (error != Error::NONE) { + return; + } + if (outSupported) { + *outSupported = tmpSupported; + } + }); + + if (!ret.isOk()) { + error = kTransactionError; + } + + if (error != Error::NONE) { + ALOGE("isSupported(%u, %u, %d, %u, ...) failed with %d", width, height, format, layerCount, + error); + } + + return static_cast(error); +} + Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(mapper) { mAllocator = IAllocator::getService(); if (mAllocator == nullptr) { diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 15597eb666..e678c58cfa 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -344,6 +344,13 @@ status_t GraphicBuffer::unlockAsync(int *fenceFd) return res; } +status_t GraphicBuffer::isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, + uint32_t inLayerCount, uint64_t inUsage, + bool* outSupported) const { + return mBufferMapper.isSupported(inWidth, inHeight, inFormat, inLayerCount, inUsage, + outSupported); +} + size_t GraphicBuffer::getFlattenedSize() const { return static_cast(13 + (handle ? mTransportNumInts : 0)) * sizeof(int); } diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index 79c333fce4..06981c39a5 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -161,5 +161,10 @@ status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd) return NO_ERROR; } +status_t GraphicBufferMapper::isSupported(uint32_t width, uint32_t height, + android::PixelFormat format, uint32_t layerCount, + uint64_t usage, bool* outSupported) { + return mMapper->isSupported(width, height, format, layerCount, usage, outSupported); +} // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h index 1b8a930c4c..6cc23f0ef8 100644 --- a/libs/ui/include/ui/Gralloc.h +++ b/libs/ui/include/ui/Gralloc.h @@ -67,6 +67,15 @@ public: // unlock returns a fence sync object (or -1) and the fence sync object is // owned by the caller virtual int unlock(buffer_handle_t bufferHandle) const = 0; + + // isSupported queries whether or not a buffer with the given width, height, + // format, layer count, and usage can be allocated on the device. If + // *outSupported is set to true, a buffer with the given specifications may be successfully + // allocated if resources are available. If false, a buffer with the given specifications will + // never successfully allocate on this device. Note that this function is not guaranteed to be + // supported on all devices, in which case a status_t of INVALID_OPERATION will be returned. + virtual status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format, + uint32_t layerCount, uint64_t usage, bool* outSupported) const = 0; }; // A wrapper to IAllocator diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h index 4ef9b51e4f..948f5976eb 100644 --- a/libs/ui/include/ui/Gralloc2.h +++ b/libs/ui/include/ui/Gralloc2.h @@ -61,6 +61,9 @@ public: int unlock(buffer_handle_t bufferHandle) const override; + status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format, + uint32_t layerCount, uint64_t usage, bool* outSupported) const override; + private: // Determines whether the passed info is compatible with the mapper. status_t validateBufferDescriptorInfo( diff --git a/libs/ui/include/ui/Gralloc3.h b/libs/ui/include/ui/Gralloc3.h index 879e96ed40..0965f52772 100644 --- a/libs/ui/include/ui/Gralloc3.h +++ b/libs/ui/include/ui/Gralloc3.h @@ -60,6 +60,9 @@ public: int unlock(buffer_handle_t bufferHandle) const override; + status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format, + uint32_t layerCount, uint64_t usage, bool* outSupported) const override; + private: // Determines whether the passed info is compatible with the mapper. status_t validateBufferDescriptorInfo( diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 18a27a01dd..7d88c58937 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -191,6 +191,9 @@ public: android_ycbcr *ycbcr, int fenceFd); status_t unlockAsync(int *fenceFd); + status_t isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, + uint32_t inLayerCount, uint64_t inUsage, bool* outSupported) const; + ANativeWindowBuffer* getNativeBuffer() const; // for debugging diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h index 072926ff44..77c99ccd07 100644 --- a/libs/ui/include/ui/GraphicBufferMapper.h +++ b/libs/ui/include/ui/GraphicBufferMapper.h @@ -78,6 +78,9 @@ public: status_t unlockAsync(buffer_handle_t handle, int *fenceFd); + status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format, + uint32_t layerCount, uint64_t usage, bool* outSupported); + const GrallocMapper& getGrallocMapper() const { return reinterpret_cast(*mMapper); } -- cgit v1.2.3-59-g8ed1b From b94adfd97b0c0d1507a30c8f7e3bd75c91aebdc2 Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Thu, 7 Feb 2019 14:25:12 -0800 Subject: Adding 3.0 mapper support to lockAsync Bug: 123423521 Test: build, boot, GraphicBuffer_test Change-Id: Id7c0a2f5d7b942e612ff7e8a5e047511f80f81bc --- libs/ui/GraphicBuffer.cpp | 24 ++++++++++++------------ libs/ui/include/ui/GraphicBuffer.h | 14 +++++++++----- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index e678c58cfa..41ae2531cd 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -286,22 +286,22 @@ status_t GraphicBuffer::unlock() return res; } -status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd) -{ +status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd, + int32_t* outBytesPerPixel, int32_t* outBytesPerStride) { const Rect lockBounds(width, height); - status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd); + status_t res = + lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride); return res; } -status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, - void** vaddr, int fenceFd) -{ - return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd); +status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd, + int32_t* outBytesPerPixel, int32_t* outBytesPerStride) { + return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride); } -status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, - uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd) -{ +status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage, + const Rect& rect, void** vaddr, int fenceFd, + int32_t* outBytesPerPixel, int32_t* outBytesPerStride) { if (rect.left < 0 || rect.right > width || rect.top < 0 || rect.bottom > height) { ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", @@ -310,9 +310,9 @@ status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, return BAD_VALUE; } - int32_t bytesPerPixel, bytesPerStride; status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, inConsumerUsage, rect, - vaddr, fenceFd, &bytesPerPixel, &bytesPerStride); + vaddr, fenceFd, outBytesPerPixel, outBytesPerStride); + return res; } diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 7d88c58937..4d4ee68194 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -180,11 +180,15 @@ public: status_t lockYCbCr(uint32_t inUsage, const Rect& rect, android_ycbcr *ycbcr); status_t unlock(); - status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd); - status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, - int fenceFd); - status_t lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage, - const Rect& rect, void** vaddr, int fenceFd); + // For the following three lockAsync functions, if bytesPerStride or bytesPerPixel + // are unknown or variable, -1 will be returned + status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd, + int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr); + status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd, + int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr); + status_t lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage, const Rect& rect, + void** vaddr, int fenceFd, int32_t* outBytesPerPixel = nullptr, + int32_t* outBytesPerStride = nullptr); status_t lockAsyncYCbCr(uint32_t inUsage, android_ycbcr *ycbcr, int fenceFd); status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect, -- cgit v1.2.3-59-g8ed1b From 727ede4a0fd4fbc6621833b21579da255eb1fb68 Mon Sep 17 00:00:00 2001 From: Tianyu Jiang Date: Fri, 1 Feb 2019 11:44:51 -0800 Subject: Fix non camelCase function names Android Framework C++ Code Style Guidelines says that function names should be camelCase: http://go/droidcppstyle Test: m, mma in frameworks/native Bug: 68273829 Change-Id: I2f661c06b31b2e72cd0eee3d91b95531b60ec939 --- libs/ui/BufferHubBuffer.cpp | 62 ++--- libs/ui/BufferHubMetadata.cpp | 8 +- libs/ui/GraphicBuffer.cpp | 2 +- libs/ui/include/ui/BufferHubBuffer.h | 28 +-- libs/ui/include/ui/BufferHubDefs.h | 16 +- libs/ui/include/ui/BufferHubMetadata.h | 14 +- libs/ui/tests/BufferHubBuffer_test.cpp | 272 ++++++++++----------- libs/ui/tests/BufferHubMetadata_test.cpp | 101 ++++---- libs/ui/tests/GraphicBuffer_test.cpp | 8 +- libs/vr/libbufferhub/buffer_hub-test.cpp | 46 ++-- libs/vr/libbufferhub/consumer_buffer.cpp | 6 +- .../include/private/dvr/buffer_hub_defs.h | 32 +-- libs/vr/libbufferhub/producer_buffer.cpp | 20 +- .../libbufferhubqueue/buffer_hub_queue_client.cpp | 4 +- services/bufferhub/BufferHubService.cpp | 22 +- services/bufferhub/BufferNode.cpp | 20 +- services/bufferhub/include/bufferhub/BufferNode.h | 16 +- services/bufferhub/tests/BufferNode_test.cpp | 47 ++-- services/vr/bufferhubd/producer_channel.cpp | 22 +- services/vr/bufferhubd/producer_queue_channel.cpp | 2 +- 20 files changed, 373 insertions(+), 375 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp index c3144b924d..7693fcbfe0 100644 --- a/libs/ui/BufferHubBuffer.cpp +++ b/libs/ui/BufferHubBuffer.cpp @@ -24,12 +24,12 @@ #include using ::android::base::unique_fd; -using ::android::BufferHubDefs::AnyClientAcquired; -using ::android::BufferHubDefs::AnyClientGained; -using ::android::BufferHubDefs::IsClientAcquired; -using ::android::BufferHubDefs::IsClientGained; -using ::android::BufferHubDefs::IsClientPosted; -using ::android::BufferHubDefs::IsClientReleased; +using ::android::BufferHubDefs::isAnyClientAcquired; +using ::android::BufferHubDefs::isAnyClientGained; +using ::android::BufferHubDefs::isClientAcquired; +using ::android::BufferHubDefs::isClientGained; +using ::android::BufferHubDefs::isClientPosted; +using ::android::BufferHubDefs::isClientReleased; using ::android::frameworks::bufferhub::V1_0::BufferHubStatus; using ::android::frameworks::bufferhub::V1_0::BufferTraits; using ::android::frameworks::bufferhub::V1_0::IBufferClient; @@ -39,22 +39,22 @@ using ::android::hardware::graphics::common::V1_2::HardwareBufferDescription; namespace android { -std::unique_ptr BufferHubBuffer::Create(uint32_t width, uint32_t height, +std::unique_ptr BufferHubBuffer::create(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, uint64_t usage, size_t userMetadataSize) { auto buffer = std::unique_ptr( new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize)); - return buffer->IsValid() ? std::move(buffer) : nullptr; + return buffer->isValid() ? std::move(buffer) : nullptr; } -std::unique_ptr BufferHubBuffer::Import(const native_handle_t* token) { +std::unique_ptr BufferHubBuffer::import(const native_handle_t* token) { if (token == nullptr) { ALOGE("%s: token cannot be nullptr!", __FUNCTION__); return nullptr; } auto buffer = std::unique_ptr(new BufferHubBuffer(token)); - return buffer->IsValid() ? std::move(buffer) : nullptr; + return buffer->isValid() ? std::move(buffer) : nullptr; } BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, @@ -169,8 +169,8 @@ int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) { // Import fds. Dup fds because hidl_handle owns the fds. unique_fd ashmemFd(fcntl(bufferTraits.bufferInfo->data[0], F_DUPFD_CLOEXEC, 0)); - mMetadata = BufferHubMetadata::Import(std::move(ashmemFd)); - if (!mMetadata.IsValid()) { + mMetadata = BufferHubMetadata::import(std::move(ashmemFd)); + if (!mMetadata.isValid()) { ALOGE("%s: Received an invalid metadata.", __FUNCTION__); return -EINVAL; } @@ -196,20 +196,20 @@ int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) { uint32_t userMetadataSize; memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[4], sizeof(userMetadataSize)); - if (mMetadata.user_metadata_size() != userMetadataSize) { + if (mMetadata.userMetadataSize() != userMetadataSize) { ALOGE("%s: user metadata size not match: expected %u, actual %zu.", __FUNCTION__, - userMetadataSize, mMetadata.user_metadata_size()); + userMetadataSize, mMetadata.userMetadataSize()); return -EINVAL; } - size_t metadataSize = static_cast(mMetadata.metadata_size()); + size_t metadataSize = static_cast(mMetadata.metadataSize()); if (metadataSize < BufferHubDefs::kMetadataHeaderSize) { ALOGE("%s: metadata too small: %zu", __FUNCTION__, metadataSize); return -EINVAL; } // Populate shortcuts to the atomics in metadata. - auto metadata_header = mMetadata.metadata_header(); + auto metadata_header = mMetadata.metadataHeader(); mBufferState = &metadata_header->buffer_state; mFenceState = &metadata_header->fence_state; mActiveClientsBitMask = &metadata_header->active_clients_bit_mask; @@ -235,16 +235,16 @@ int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) { return 0; } -int BufferHubBuffer::Gain() { +int BufferHubBuffer::gain() { uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire); - if (IsClientGained(currentBufferState, mClientStateMask)) { + if (isClientGained(currentBufferState, mClientStateMask)) { ALOGV("%s: Buffer is already gained by this client %" PRIx32 ".", __FUNCTION__, mClientStateMask); return 0; } do { - if (AnyClientGained(currentBufferState & (~mClientStateMask)) || - AnyClientAcquired(currentBufferState)) { + if (isAnyClientGained(currentBufferState & (~mClientStateMask)) || + isAnyClientAcquired(currentBufferState)) { ALOGE("%s: Buffer is in use, id=%d mClientStateMask=%" PRIx32 " state=%" PRIx32 ".", __FUNCTION__, mId, mClientStateMask, currentBufferState); return -EBUSY; @@ -258,11 +258,11 @@ int BufferHubBuffer::Gain() { return 0; } -int BufferHubBuffer::Post() { +int BufferHubBuffer::post() { uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire); uint32_t updatedBufferState = (~mClientStateMask) & BufferHubDefs::kHighBitsMask; do { - if (!IsClientGained(currentBufferState, mClientStateMask)) { + if (!isClientGained(currentBufferState, mClientStateMask)) { ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d " "mClientStateMask=%" PRIx32 " state=%" PRIx32 ".", __FUNCTION__, mId, mClientStateMask, currentBufferState); @@ -277,16 +277,16 @@ int BufferHubBuffer::Post() { return 0; } -int BufferHubBuffer::Acquire() { +int BufferHubBuffer::acquire() { uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire); - if (IsClientAcquired(currentBufferState, mClientStateMask)) { + if (isClientAcquired(currentBufferState, mClientStateMask)) { ALOGV("%s: Buffer is already acquired by this client %" PRIx32 ".", __FUNCTION__, mClientStateMask); return 0; } uint32_t updatedBufferState = 0U; do { - if (!IsClientPosted(currentBufferState, mClientStateMask)) { + if (!isClientPosted(currentBufferState, mClientStateMask)) { ALOGE("%s: Cannot acquire a buffer that is not in posted state. buffer_id=%d " "mClientStateMask=%" PRIx32 " state=%" PRIx32 ".", __FUNCTION__, mId, mClientStateMask, currentBufferState); @@ -301,9 +301,9 @@ int BufferHubBuffer::Acquire() { return 0; } -int BufferHubBuffer::Release() { +int BufferHubBuffer::release() { uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire); - if (IsClientReleased(currentBufferState, mClientStateMask)) { + if (isClientReleased(currentBufferState, mClientStateMask)) { ALOGV("%s: Buffer is already released by this client %" PRIx32 ".", __FUNCTION__, mClientStateMask); return 0; @@ -318,17 +318,17 @@ int BufferHubBuffer::Release() { return 0; } -bool BufferHubBuffer::IsReleased() const { +bool BufferHubBuffer::isReleased() const { return (mBufferState->load(std::memory_order_acquire) & mActiveClientsBitMask->load(std::memory_order_acquire)) == 0; } -bool BufferHubBuffer::IsValid() const { +bool BufferHubBuffer::isValid() const { return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U && - mEventFd.get() >= 0 && mMetadata.IsValid() && mBufferClient != nullptr; + mEventFd.get() >= 0 && mMetadata.isValid() && mBufferClient != nullptr; } -native_handle_t* BufferHubBuffer::Duplicate() { +native_handle_t* BufferHubBuffer::duplicate() { if (mBufferClient == nullptr) { ALOGE("%s: missing BufferClient!", __FUNCTION__); return nullptr; diff --git a/libs/ui/BufferHubMetadata.cpp b/libs/ui/BufferHubMetadata.cpp index 816707db9d..05bc7ddfbe 100644 --- a/libs/ui/BufferHubMetadata.cpp +++ b/libs/ui/BufferHubMetadata.cpp @@ -34,7 +34,7 @@ using BufferHubDefs::kMetadataHeaderSize; using BufferHubDefs::MetadataHeader; /* static */ -BufferHubMetadata BufferHubMetadata::Create(size_t userMetadataSize) { +BufferHubMetadata BufferHubMetadata::create(size_t userMetadataSize) { // The size the of metadata buffer is used as the "width" parameter during allocation. Thus it // cannot overflow uint32_t. if (userMetadataSize >= (std::numeric_limits::max() - kMetadataHeaderSize)) { @@ -59,11 +59,11 @@ BufferHubMetadata BufferHubMetadata::Create(size_t userMetadataSize) { return {}; } - return BufferHubMetadata::Import(std::move(ashmemFd)); + return BufferHubMetadata::import(std::move(ashmemFd)); } /* static */ -BufferHubMetadata BufferHubMetadata::Import(unique_fd ashmemFd) { +BufferHubMetadata BufferHubMetadata::import(unique_fd ashmemFd) { if (!ashmem_valid(ashmemFd.get())) { ALOGE("BufferHubMetadata::Import: invalid ashmem fd."); return {}; @@ -94,7 +94,7 @@ BufferHubMetadata::BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd BufferHubMetadata::~BufferHubMetadata() { if (mMetadataHeader != nullptr) { - int ret = munmap(mMetadataHeader, metadata_size()); + int ret = munmap(mMetadataHeader, metadataSize()); ALOGE_IF(ret != 0, "BufferHubMetadata::~BufferHubMetadata: failed to unmap ashmem, error=%d.", errno); mMetadataHeader = nullptr; diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 41ae2531cd..f487dfa81b 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -100,7 +100,7 @@ GraphicBuffer::GraphicBuffer(std::unique_ptr buffer) : GraphicB return; } - mInitCheck = initWithHandle(buffer->DuplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE, + mInitCheck = initWithHandle(buffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE, buffer->desc().width, buffer->desc().height, static_cast(buffer->desc().format), buffer->desc().layers, buffer->desc().usage, buffer->desc().stride); diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h index 06955e4161..eac8c8437b 100644 --- a/libs/ui/include/ui/BufferHubBuffer.h +++ b/libs/ui/include/ui/BufferHubBuffer.h @@ -29,14 +29,14 @@ namespace android { class BufferHubBuffer { public: // Allocates a standalone BufferHubBuffer. - static std::unique_ptr Create(uint32_t width, uint32_t height, + static std::unique_ptr create(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, uint64_t usage, size_t userMetadataSize); // Imports the given token to a BufferHubBuffer. Not taking ownership of the token. Caller // should close and destroy the token after calling this function regardless of output. // TODO(b/122543147): use a movable wrapper for token - static std::unique_ptr Import(const native_handle_t* token); + static std::unique_ptr import(const native_handle_t* token); BufferHubBuffer(const BufferHubBuffer&) = delete; void operator=(const BufferHubBuffer&) = delete; @@ -52,51 +52,51 @@ public: // Duplicate the underlying Gralloc buffer handle. Caller is responsible to free the handle // after use. - native_handle_t* DuplicateHandle() { + native_handle_t* duplicateHandle() { return native_handle_clone(mBufferHandle.getNativeHandle()); } const BufferHubEventFd& eventFd() const { return mEventFd; } // Returns the current value of MetadataHeader::buffer_state. - uint32_t buffer_state() const { return mBufferState->load(std::memory_order_acquire); } + uint32_t bufferState() const { return mBufferState->load(std::memory_order_acquire); } // A state mask which is unique to a buffer hub client among all its siblings sharing the same // concrete graphic buffer. - uint32_t client_state_mask() const { return mClientStateMask; } + uint32_t clientStateMask() const { return mClientStateMask; } - size_t user_metadata_size() const { return mMetadata.user_metadata_size(); } + size_t userMetadataSize() const { return mMetadata.userMetadataSize(); } // Returns true if the BufferClient is still alive. - bool IsConnected() const { return mBufferClient->ping().isOk(); } + bool isConnected() const { return mBufferClient->ping().isOk(); } // Returns true if the buffer is valid: non-null buffer handle, valid id, valid client bit mask, // valid metadata and valid buffer client - bool IsValid() const; + bool isValid() const; // Gains the buffer for exclusive write permission. Read permission is implied once a buffer is // gained. // The buffer can be gained as long as there is no other client in acquired or gained state. - int Gain(); + int gain(); // Posts the gained buffer for other buffer clients to use the buffer. // The buffer can be posted iff the buffer state for this client is gained. // After posting the buffer, this client is put to released state and does not have access to // the buffer for this cycle of the usage of the buffer. - int Post(); + int post(); // Acquires the buffer for shared read permission. // The buffer can be acquired iff the buffer state for this client is posted. - int Acquire(); + int acquire(); // Releases the buffer. // The buffer can be released from any buffer state. // After releasing the buffer, this client no longer have any permissions to the buffer for the // current cycle of the usage of the buffer. - int Release(); + int release(); // Returns whether the buffer is released by all active clients or not. - bool IsReleased() const; + bool isReleased() const; // Creates a token that stands for this BufferHubBuffer client and could be used for Import to // create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying @@ -104,7 +104,7 @@ public: // should free it after use. // Returns a valid token on success, nullptr on failure. // TODO(b/122543147): use a movable wrapper for token - native_handle_t* Duplicate(); + native_handle_t* duplicate(); private: BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, diff --git a/libs/ui/include/ui/BufferHubDefs.h b/libs/ui/include/ui/BufferHubDefs.h index ff970cbd64..722a060597 100644 --- a/libs/ui/include/ui/BufferHubDefs.h +++ b/libs/ui/include/ui/BufferHubDefs.h @@ -63,19 +63,19 @@ static constexpr uint32_t kHighBitsMask = ~kLowbitsMask; static constexpr uint32_t kFirstClientBitMask = (1U << kMaxNumberOfClients) + 1U; // Returns true if any of the client is in gained state. -static inline bool AnyClientGained(uint32_t state) { +static inline bool isAnyClientGained(uint32_t state) { uint32_t high_bits = state >> kMaxNumberOfClients; uint32_t low_bits = state & kLowbitsMask; return high_bits == low_bits && low_bits != 0U; } // Returns true if the input client is in gained state. -static inline bool IsClientGained(uint32_t state, uint32_t client_bit_mask) { +static inline bool isClientGained(uint32_t state, uint32_t client_bit_mask) { return state == client_bit_mask; } // Returns true if any of the client is in posted state. -static inline bool AnyClientPosted(uint32_t state) { +static inline bool isAnyClientPosted(uint32_t state) { uint32_t high_bits = state >> kMaxNumberOfClients; uint32_t low_bits = state & kLowbitsMask; uint32_t posted_or_acquired = high_bits ^ low_bits; @@ -83,7 +83,7 @@ static inline bool AnyClientPosted(uint32_t state) { } // Returns true if the input client is in posted state. -static inline bool IsClientPosted(uint32_t state, uint32_t client_bit_mask) { +static inline bool isClientPosted(uint32_t state, uint32_t client_bit_mask) { uint32_t client_bits = state & client_bit_mask; if (client_bits == 0U) return false; uint32_t low_bits = client_bits & kLowbitsMask; @@ -91,7 +91,7 @@ static inline bool IsClientPosted(uint32_t state, uint32_t client_bit_mask) { } // Return true if any of the client is in acquired state. -static inline bool AnyClientAcquired(uint32_t state) { +static inline bool isAnyClientAcquired(uint32_t state) { uint32_t high_bits = state >> kMaxNumberOfClients; uint32_t low_bits = state & kLowbitsMask; uint32_t posted_or_acquired = high_bits ^ low_bits; @@ -99,7 +99,7 @@ static inline bool AnyClientAcquired(uint32_t state) { } // Return true if the input client is in acquired state. -static inline bool IsClientAcquired(uint32_t state, uint32_t client_bit_mask) { +static inline bool isClientAcquired(uint32_t state, uint32_t client_bit_mask) { uint32_t client_bits = state & client_bit_mask; if (client_bits == 0U) return false; uint32_t high_bits = client_bits & kHighBitsMask; @@ -107,13 +107,13 @@ static inline bool IsClientAcquired(uint32_t state, uint32_t client_bit_mask) { } // Returns true if the input client is in released state. -static inline bool IsClientReleased(uint32_t state, uint32_t client_bit_mask) { +static inline bool isClientReleased(uint32_t state, uint32_t client_bit_mask) { return (state & client_bit_mask) == 0U; } // Returns the next available buffer client's client_state_masks. // @params union_bits. Union of all existing clients' client_state_masks. -static inline uint32_t FindNextAvailableClientStateMask(uint32_t union_bits) { +static inline uint32_t findNextAvailableClientStateMask(uint32_t union_bits) { uint32_t low_union = union_bits & kLowbitsMask; if (low_union == kLowbitsMask) return 0U; uint32_t incremented = low_union + 1U; diff --git a/libs/ui/include/ui/BufferHubMetadata.h b/libs/ui/include/ui/BufferHubMetadata.h index 212189497a..3482507399 100644 --- a/libs/ui/include/ui/BufferHubMetadata.h +++ b/libs/ui/include/ui/BufferHubMetadata.h @@ -33,12 +33,12 @@ public: // @param userMetadataSize Size in bytes of the user defined metadata. The entire metadata // shared memory region to be allocated is the size of canonical // BufferHubDefs::MetadataHeader plus userMetadataSize. - static BufferHubMetadata Create(size_t userMetadataSize); + static BufferHubMetadata create(size_t userMetadataSize); // Imports an existing BufferHubMetadata from an ashmem FD. // // @param ashmemFd Ashmem file descriptor representing an ashmem region. - static BufferHubMetadata Import(unique_fd ashmemFd); + static BufferHubMetadata import(unique_fd ashmemFd); BufferHubMetadata() = default; @@ -63,13 +63,13 @@ public: // Returns true if the metadata is valid, i.e. the metadata has a valid ashmem fd and the ashmem // has been mapped into virtual address space. - bool IsValid() const { return mAshmemFd.get() != -1 && mMetadataHeader != nullptr; } + bool isValid() const { return mAshmemFd.get() != -1 && mMetadataHeader != nullptr; } - size_t user_metadata_size() const { return mUserMetadataSize; } - size_t metadata_size() const { return mUserMetadataSize + BufferHubDefs::kMetadataHeaderSize; } + size_t userMetadataSize() const { return mUserMetadataSize; } + size_t metadataSize() const { return mUserMetadataSize + BufferHubDefs::kMetadataHeaderSize; } - const unique_fd& ashmem_fd() const { return mAshmemFd; } - BufferHubDefs::MetadataHeader* metadata_header() { return mMetadataHeader; } + const unique_fd& ashmemFd() const { return mAshmemFd; } + BufferHubDefs::MetadataHeader* metadataHeader() { return mMetadataHeader; } private: BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd, diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp index 4ad2c4c2ce..3087a90787 100644 --- a/libs/ui/tests/BufferHubBuffer_test.cpp +++ b/libs/ui/tests/BufferHubBuffer_test.cpp @@ -32,13 +32,13 @@ namespace android { namespace { -using ::android::BufferHubDefs::AnyClientAcquired; -using ::android::BufferHubDefs::AnyClientGained; -using ::android::BufferHubDefs::AnyClientPosted; -using ::android::BufferHubDefs::IsClientAcquired; -using ::android::BufferHubDefs::IsClientGained; -using ::android::BufferHubDefs::IsClientPosted; -using ::android::BufferHubDefs::IsClientReleased; +using ::android::BufferHubDefs::isAnyClientAcquired; +using ::android::BufferHubDefs::isAnyClientGained; +using ::android::BufferHubDefs::isAnyClientPosted; +using ::android::BufferHubDefs::isClientAcquired; +using ::android::BufferHubDefs::isClientGained; +using ::android::BufferHubDefs::isClientPosted; +using ::android::BufferHubDefs::isClientReleased; using ::android::BufferHubDefs::kMetadataHeaderSize; using ::testing::IsNull; using ::testing::NotNull; @@ -81,88 +81,88 @@ private: }; void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() { - b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); + b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); ASSERT_THAT(b1, NotNull()); - b1ClientMask = b1->client_state_mask(); + b1ClientMask = b1->clientStateMask(); ASSERT_NE(b1ClientMask, 0U); - native_handle_t* token = b1->Duplicate(); + native_handle_t* token = b1->duplicate(); ASSERT_THAT(token, NotNull()); // TODO(b/122543147): use a movalbe wrapper for token - b2 = BufferHubBuffer::Import(token); + b2 = BufferHubBuffer::import(token); native_handle_close(token); native_handle_delete(token); ASSERT_THAT(b2, NotNull()); - b2ClientMask = b2->client_state_mask(); + b2ClientMask = b2->clientStateMask(); ASSERT_NE(b2ClientMask, 0U); ASSERT_NE(b2ClientMask, b1ClientMask); } TEST_F(BufferHubBufferTest, CreateBufferFails) { // Buffer Creation will fail: BLOB format requires height to be 1. - auto b1 = BufferHubBuffer::Create(kWidth, /*height=*/2, kLayerCount, + auto b1 = BufferHubBuffer::create(kWidth, /*height=*/2, kLayerCount, /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage, kUserMetadataSize); EXPECT_THAT(b1, IsNull()); // Buffer Creation will fail: user metadata size too large. - auto b2 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, + auto b2 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, /*userMetadataSize=*/std::numeric_limits::max()); EXPECT_THAT(b2, IsNull()); // Buffer Creation will fail: user metadata size too large. const size_t userMetadataSize = std::numeric_limits::max() - kMetadataHeaderSize; - auto b3 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, + auto b3 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, userMetadataSize); EXPECT_THAT(b3, IsNull()); } TEST_F(BufferHubBufferTest, CreateBuffer) { - auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, + auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); ASSERT_THAT(b1, NotNull()); - EXPECT_TRUE(b1->IsConnected()); - EXPECT_TRUE(b1->IsValid()); + EXPECT_TRUE(b1->isConnected()); + EXPECT_TRUE(b1->isValid()); EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), kDesc)); - EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize); + EXPECT_EQ(b1->userMetadataSize(), kUserMetadataSize); } TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) { - auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, + auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); ASSERT_THAT(b1, NotNull()); - EXPECT_TRUE(b1->IsValid()); + EXPECT_TRUE(b1->isValid()); - native_handle_t* token = b1->Duplicate(); + native_handle_t* token = b1->duplicate(); EXPECT_TRUE(token); // The detached buffer should still be valid. - EXPECT_TRUE(b1->IsConnected()); - EXPECT_TRUE(b1->IsValid()); + EXPECT_TRUE(b1->isConnected()); + EXPECT_TRUE(b1->isValid()); - std::unique_ptr b2 = BufferHubBuffer::Import(token); + std::unique_ptr b2 = BufferHubBuffer::import(token); native_handle_close(token); native_handle_delete(token); ASSERT_THAT(b2, NotNull()); - EXPECT_TRUE(b2->IsValid()); + EXPECT_TRUE(b2->isValid()); EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), b2->desc())); - EXPECT_EQ(b1->user_metadata_size(), b2->user_metadata_size()); + EXPECT_EQ(b1->userMetadataSize(), b2->userMetadataSize()); // These two buffer instances are based on the same physical buffer under the // hood, so they should share the same id. EXPECT_EQ(b1->id(), b2->id()); - // We use client_state_mask() to tell those two instances apart. - EXPECT_NE(b1->client_state_mask(), b2->client_state_mask()); + // We use clientStateMask() to tell those two instances apart. + EXPECT_NE(b1->clientStateMask(), b2->clientStateMask()); // Both buffer instances should be in released state currently. - EXPECT_TRUE(b1->IsReleased()); - EXPECT_TRUE(b2->IsReleased()); + EXPECT_TRUE(b1->isReleased()); + EXPECT_TRUE(b2->isReleased()); // The event fd should behave like duped event fds. const BufferHubEventFd& eventFd1 = b1->eventFd(); @@ -192,19 +192,19 @@ TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) { } TEST_F(BufferHubBufferTest, ImportFreedBuffer) { - auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, + auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); ASSERT_THAT(b1, NotNull()); - EXPECT_TRUE(b1->IsValid()); + EXPECT_TRUE(b1->isValid()); - native_handle_t* token = b1->Duplicate(); + native_handle_t* token = b1->duplicate(); EXPECT_TRUE(token); // Explicitly destroy b1. Backend buffer should be freed and token becomes invalid b1.reset(); // TODO(b/122543147): use a movalbe wrapper for token - std::unique_ptr b2 = BufferHubBuffer::Import(token); + std::unique_ptr b2 = BufferHubBuffer::import(token); native_handle_close(token); native_handle_delete(token); @@ -214,7 +214,7 @@ TEST_F(BufferHubBufferTest, ImportFreedBuffer) { // nullptr must not crash the service TEST_F(BufferHubBufferTest, ImportNullToken) { - auto b1 = BufferHubBuffer::Import(nullptr); + auto b1 = BufferHubBuffer::import(nullptr); EXPECT_THAT(b1, IsNull()); } @@ -222,185 +222,185 @@ TEST_F(BufferHubBufferTest, ImportInvalidToken) { native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1); token->data[0] = 0; - auto b1 = BufferHubBuffer::Import(token); + auto b1 = BufferHubBuffer::import(token); native_handle_delete(token); EXPECT_THAT(b1, IsNull()); } TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) { - ASSERT_TRUE(b1->IsReleased()); + ASSERT_TRUE(b1->isReleased()); // Successful gaining the buffer should change the buffer state bit of b1 to // gained state, other client state bits to released state. - EXPECT_EQ(b1->Gain(), 0); - EXPECT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask)); + EXPECT_EQ(b1->gain(), 0); + EXPECT_TRUE(isClientGained(b1->bufferState(), b1ClientMask)); } TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromGainedState) { - ASSERT_EQ(b1->Gain(), 0); - auto currentBufferState = b1->buffer_state(); - ASSERT_TRUE(IsClientGained(currentBufferState, b1ClientMask)); + ASSERT_EQ(b1->gain(), 0); + auto currentBufferState = b1->bufferState(); + ASSERT_TRUE(isClientGained(currentBufferState, b1ClientMask)); // Gaining from gained state by the same client should not return error. - EXPECT_EQ(b1->Gain(), 0); + EXPECT_EQ(b1->gain(), 0); // Gaining from gained state by another client should return error. - EXPECT_EQ(b2->Gain(), -EBUSY); + EXPECT_EQ(b2->gain(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromAcquiredState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_EQ(b2->Acquire(), 0); - ASSERT_TRUE(AnyClientAcquired(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_EQ(b2->acquire(), 0); + ASSERT_TRUE(isAnyClientAcquired(b1->bufferState())); // Gaining from acquired state should fail. - EXPECT_EQ(b1->Gain(), -EBUSY); - EXPECT_EQ(b2->Gain(), -EBUSY); + EXPECT_EQ(b1->gain(), -EBUSY); + EXPECT_EQ(b2->gain(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromOtherClientInPostedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_TRUE(AnyClientPosted(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); // Gaining a buffer who has other posted client should succeed. - EXPECT_EQ(b1->Gain(), 0); + EXPECT_EQ(b1->gain(), 0); } TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromSelfInPostedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_TRUE(AnyClientPosted(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); // A posted client should be able to gain the buffer when there is no other clients in // acquired state. - EXPECT_EQ(b2->Gain(), 0); + EXPECT_EQ(b2->gain(), 0); } TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromOtherInGainedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask)); + ASSERT_EQ(b1->gain(), 0); + ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask)); - EXPECT_EQ(b2->Post(), -EBUSY); + EXPECT_EQ(b2->post(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromSelfInGainedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask)); + ASSERT_EQ(b1->gain(), 0); + ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask)); - EXPECT_EQ(b1->Post(), 0); - auto currentBufferState = b1->buffer_state(); - EXPECT_TRUE(IsClientReleased(currentBufferState, b1ClientMask)); - EXPECT_TRUE(IsClientPosted(currentBufferState, b2ClientMask)); + EXPECT_EQ(b1->post(), 0); + auto currentBufferState = b1->bufferState(); + EXPECT_TRUE(isClientReleased(currentBufferState, b1ClientMask)); + EXPECT_TRUE(isClientPosted(currentBufferState, b2ClientMask)); } TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromPostedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_TRUE(AnyClientPosted(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); // Post from posted state should fail. - EXPECT_EQ(b1->Post(), -EBUSY); - EXPECT_EQ(b2->Post(), -EBUSY); + EXPECT_EQ(b1->post(), -EBUSY); + EXPECT_EQ(b2->post(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromAcquiredState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_EQ(b2->Acquire(), 0); - ASSERT_TRUE(AnyClientAcquired(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_EQ(b2->acquire(), 0); + ASSERT_TRUE(isAnyClientAcquired(b1->bufferState())); // Posting from acquired state should fail. - EXPECT_EQ(b1->Post(), -EBUSY); - EXPECT_EQ(b2->Post(), -EBUSY); + EXPECT_EQ(b1->post(), -EBUSY); + EXPECT_EQ(b2->post(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromReleasedState) { - ASSERT_TRUE(b1->IsReleased()); + ASSERT_TRUE(b1->isReleased()); // Posting from released state should fail. - EXPECT_EQ(b1->Post(), -EBUSY); - EXPECT_EQ(b2->Post(), -EBUSY); + EXPECT_EQ(b1->post(), -EBUSY); + EXPECT_EQ(b2->post(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInPostedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask)); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask)); // Acquire from posted state should pass. - EXPECT_EQ(b2->Acquire(), 0); + EXPECT_EQ(b2->acquire(), 0); } TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromOtherInPostedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask)); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask)); // Acquire from released state should fail, although there are other clients // in posted state. - EXPECT_EQ(b1->Acquire(), -EBUSY); + EXPECT_EQ(b1->acquire(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInAcquiredState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_EQ(b2->Acquire(), 0); - auto currentBufferState = b1->buffer_state(); - ASSERT_TRUE(IsClientAcquired(currentBufferState, b2ClientMask)); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_EQ(b2->acquire(), 0); + auto currentBufferState = b1->bufferState(); + ASSERT_TRUE(isClientAcquired(currentBufferState, b2ClientMask)); // Acquiring from acquired state by the same client should not error out. - EXPECT_EQ(b2->Acquire(), 0); + EXPECT_EQ(b2->acquire(), 0); } TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromReleasedState) { - ASSERT_TRUE(b1->IsReleased()); + ASSERT_TRUE(b1->isReleased()); // Acquiring form released state should fail. - EXPECT_EQ(b1->Acquire(), -EBUSY); - EXPECT_EQ(b2->Acquire(), -EBUSY); + EXPECT_EQ(b1->acquire(), -EBUSY); + EXPECT_EQ(b2->acquire(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromGainedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_TRUE(AnyClientGained(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_TRUE(isAnyClientGained(b1->bufferState())); // Acquiring from gained state should fail. - EXPECT_EQ(b1->Acquire(), -EBUSY); - EXPECT_EQ(b2->Acquire(), -EBUSY); + EXPECT_EQ(b1->acquire(), -EBUSY); + EXPECT_EQ(b2->acquire(), -EBUSY); } TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInReleasedState) { - ASSERT_TRUE(b1->IsReleased()); + ASSERT_TRUE(b1->isReleased()); - EXPECT_EQ(b1->Release(), 0); + EXPECT_EQ(b1->release(), 0); } TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInGainedState) { - ASSERT_TRUE(b1->IsReleased()); - ASSERT_EQ(b1->Gain(), 0); - ASSERT_TRUE(AnyClientGained(b1->buffer_state())); + ASSERT_TRUE(b1->isReleased()); + ASSERT_EQ(b1->gain(), 0); + ASSERT_TRUE(isAnyClientGained(b1->bufferState())); - EXPECT_EQ(b1->Release(), 0); + EXPECT_EQ(b1->release(), 0); } TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInPostedState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_TRUE(AnyClientPosted(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); - EXPECT_EQ(b2->Release(), 0); + EXPECT_EQ(b2->release(), 0); } TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInAcquiredState) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_EQ(b2->Acquire(), 0); - ASSERT_TRUE(AnyClientAcquired(b1->buffer_state())); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_EQ(b2->acquire(), 0); + ASSERT_TRUE(isAnyClientAcquired(b1->bufferState())); - EXPECT_EQ(b2->Release(), 0); + EXPECT_EQ(b2->release(), 0); } TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) { @@ -408,60 +408,60 @@ TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) { // Test if this set of basic operation succeed: // Producer post three times to the consumer, and released by consumer. for (int i = 0; i < 3; ++i) { - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); - ASSERT_EQ(b2->Acquire(), 0); - ASSERT_EQ(b2->Release(), 0); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); + ASSERT_EQ(b2->acquire(), 0); + ASSERT_EQ(b2->release(), 0); } } TEST_F(BufferHubBufferTest, createNewConsumerAfterGain) { // Create a poducer buffer and gain. std::unique_ptr b1 = - BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, + BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); ASSERT_THAT(b1, NotNull()); - ASSERT_EQ(b1->Gain(), 0); + ASSERT_EQ(b1->gain(), 0); // Create a consumer of the buffer and test if the consumer can acquire the // buffer if producer posts. // TODO(b/122543147): use a movalbe wrapper for token - native_handle_t* token = b1->Duplicate(); + native_handle_t* token = b1->duplicate(); ASSERT_TRUE(token); - std::unique_ptr b2 = BufferHubBuffer::Import(token); + std::unique_ptr b2 = BufferHubBuffer::import(token); native_handle_close(token); native_handle_delete(token); ASSERT_THAT(b2, NotNull()); - ASSERT_NE(b1->client_state_mask(), b2->client_state_mask()); + ASSERT_NE(b1->clientStateMask(), b2->clientStateMask()); - ASSERT_EQ(b1->Post(), 0); - EXPECT_EQ(b2->Acquire(), 0); + ASSERT_EQ(b1->post(), 0); + EXPECT_EQ(b2->acquire(), 0); } TEST_F(BufferHubBufferTest, createNewConsumerAfterPost) { // Create a poducer buffer and post. std::unique_ptr b1 = - BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, + BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); - ASSERT_EQ(b1->Gain(), 0); - ASSERT_EQ(b1->Post(), 0); + ASSERT_EQ(b1->gain(), 0); + ASSERT_EQ(b1->post(), 0); // Create a consumer of the buffer and test if the consumer can acquire the // buffer if producer posts. // TODO(b/122543147): use a movalbe wrapper for token - native_handle_t* token = b1->Duplicate(); + native_handle_t* token = b1->duplicate(); ASSERT_TRUE(token); - std::unique_ptr b2 = BufferHubBuffer::Import(token); + std::unique_ptr b2 = BufferHubBuffer::import(token); native_handle_close(token); native_handle_delete(token); ASSERT_THAT(b2, NotNull()); - ASSERT_NE(b1->client_state_mask(), b2->client_state_mask()); + ASSERT_NE(b1->clientStateMask(), b2->clientStateMask()); - EXPECT_EQ(b2->Acquire(), 0); + EXPECT_EQ(b2->acquire(), 0); } } // namespace diff --git a/libs/ui/tests/BufferHubMetadata_test.cpp b/libs/ui/tests/BufferHubMetadata_test.cpp index b7f0b4b140..f02c4fc178 100644 --- a/libs/ui/tests/BufferHubMetadata_test.cpp +++ b/libs/ui/tests/BufferHubMetadata_test.cpp @@ -25,74 +25,73 @@ constexpr size_t kEmptyUserMetadataSize = 0; class BufferHubMetadataTest : public ::testing::Test {}; TEST_F(BufferHubMetadataTest, Create_UserMetdataSizeTooBig) { - BufferHubMetadata m1 = - BufferHubMetadata::Create(std::numeric_limits::max()); - EXPECT_FALSE(m1.IsValid()); + BufferHubMetadata m1 = BufferHubMetadata::create(std::numeric_limits::max()); + EXPECT_FALSE(m1.isValid()); } TEST_F(BufferHubMetadataTest, Create_Success) { - BufferHubMetadata m1 = BufferHubMetadata::Create(kEmptyUserMetadataSize); - EXPECT_TRUE(m1.IsValid()); - EXPECT_NE(m1.metadata_header(), nullptr); + BufferHubMetadata m1 = BufferHubMetadata::create(kEmptyUserMetadataSize); + EXPECT_TRUE(m1.isValid()); + EXPECT_NE(m1.metadataHeader(), nullptr); } TEST_F(BufferHubMetadataTest, Import_Success) { - BufferHubMetadata m1 = BufferHubMetadata::Create(kEmptyUserMetadataSize); - EXPECT_TRUE(m1.IsValid()); - EXPECT_NE(m1.metadata_header(), nullptr); - - unique_fd h2 = unique_fd(dup(m1.ashmem_fd().get())); - EXPECT_NE(h2.get(), -1); - - BufferHubMetadata m2 = BufferHubMetadata::Import(std::move(h2)); - EXPECT_EQ(h2.get(), -1); - EXPECT_TRUE(m1.IsValid()); - BufferHubDefs::MetadataHeader* mh1 = m1.metadata_header(); - EXPECT_NE(mh1, nullptr); - - // Check if the newly allocated buffer is initialized in released state (i.e. - // state equals to 0U). - EXPECT_TRUE(mh1->buffer_state.load() == 0U); - - EXPECT_TRUE(m2.IsValid()); - BufferHubDefs::MetadataHeader* mh2 = m2.metadata_header(); - EXPECT_NE(mh2, nullptr); - - // Check if the newly allocated buffer is initialized in released state (i.e. - // state equals to 0U). - EXPECT_TRUE(mh2->buffer_state.load() == 0U); + BufferHubMetadata m1 = BufferHubMetadata::create(kEmptyUserMetadataSize); + EXPECT_TRUE(m1.isValid()); + EXPECT_NE(m1.metadataHeader(), nullptr); + + unique_fd h2 = unique_fd(dup(m1.ashmemFd().get())); + EXPECT_NE(h2.get(), -1); + + BufferHubMetadata m2 = BufferHubMetadata::import(std::move(h2)); + EXPECT_EQ(h2.get(), -1); + EXPECT_TRUE(m1.isValid()); + BufferHubDefs::MetadataHeader* mh1 = m1.metadataHeader(); + EXPECT_NE(mh1, nullptr); + + // Check if the newly allocated buffer is initialized in released state (i.e. + // state equals to 0U). + EXPECT_TRUE(mh1->buffer_state.load() == 0U); + + EXPECT_TRUE(m2.isValid()); + BufferHubDefs::MetadataHeader* mh2 = m2.metadataHeader(); + EXPECT_NE(mh2, nullptr); + + // Check if the newly allocated buffer is initialized in released state (i.e. + // state equals to 0U). + EXPECT_TRUE(mh2->buffer_state.load() == 0U); } TEST_F(BufferHubMetadataTest, MoveMetadataInvalidatesOldOne) { - BufferHubMetadata m1 = BufferHubMetadata::Create(sizeof(int)); - EXPECT_TRUE(m1.IsValid()); - EXPECT_NE(m1.metadata_header(), nullptr); - EXPECT_NE(m1.ashmem_fd().get(), -1); - EXPECT_EQ(m1.user_metadata_size(), sizeof(int)); + BufferHubMetadata m1 = BufferHubMetadata::create(sizeof(int)); + EXPECT_TRUE(m1.isValid()); + EXPECT_NE(m1.metadataHeader(), nullptr); + EXPECT_NE(m1.ashmemFd().get(), -1); + EXPECT_EQ(m1.userMetadataSize(), sizeof(int)); - BufferHubMetadata m2 = std::move(m1); + BufferHubMetadata m2 = std::move(m1); - // After the move, the metadata header (a raw pointer) should be reset in the older buffer. - EXPECT_EQ(m1.metadata_header(), nullptr); - EXPECT_NE(m2.metadata_header(), nullptr); + // After the move, the metadata header (a raw pointer) should be reset in the older buffer. + EXPECT_EQ(m1.metadataHeader(), nullptr); + EXPECT_NE(m2.metadataHeader(), nullptr); - EXPECT_EQ(m1.ashmem_fd().get(), -1); - EXPECT_NE(m2.ashmem_fd().get(), -1); + EXPECT_EQ(m1.ashmemFd().get(), -1); + EXPECT_NE(m2.ashmemFd().get(), -1); - EXPECT_EQ(m1.user_metadata_size(), 0U); - EXPECT_EQ(m2.user_metadata_size(), sizeof(int)); + EXPECT_EQ(m1.userMetadataSize(), 0U); + EXPECT_EQ(m2.userMetadataSize(), sizeof(int)); - BufferHubMetadata m3{std::move(m2)}; + BufferHubMetadata m3{std::move(m2)}; - // After the move, the metadata header (a raw pointer) should be reset in the older buffer. - EXPECT_EQ(m2.metadata_header(), nullptr); - EXPECT_NE(m3.metadata_header(), nullptr); + // After the move, the metadata header (a raw pointer) should be reset in the older buffer. + EXPECT_EQ(m2.metadataHeader(), nullptr); + EXPECT_NE(m3.metadataHeader(), nullptr); - EXPECT_EQ(m2.ashmem_fd().get(), -1); - EXPECT_NE(m3.ashmem_fd().get(), -1); + EXPECT_EQ(m2.ashmemFd().get(), -1); + EXPECT_NE(m3.ashmemFd().get(), -1); - EXPECT_EQ(m2.user_metadata_size(), 0U); - EXPECT_EQ(m3.user_metadata_size(), sizeof(int)); + EXPECT_EQ(m2.userMetadataSize(), 0U); + EXPECT_EQ(m3.userMetadataSize(), sizeof(int)); } } // namespace dvr diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp index 5b46454c60..c767ce02fc 100644 --- a/libs/ui/tests/GraphicBuffer_test.cpp +++ b/libs/ui/tests/GraphicBuffer_test.cpp @@ -37,10 +37,10 @@ class GraphicBufferTest : public testing::Test {}; TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) { std::unique_ptr b1 = - BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, + BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, kTestUsage, /*userMetadataSize=*/0); ASSERT_NE(b1, nullptr); - EXPECT_TRUE(b1->IsValid()); + EXPECT_TRUE(b1->isValid()); sp gb(new GraphicBuffer(std::move(b1))); EXPECT_TRUE(gb->isBufferHubBuffer()); @@ -61,10 +61,10 @@ TEST_F(GraphicBufferTest, InvalidBufferIdForNoneBufferHubBuffer) { TEST_F(GraphicBufferTest, BufferIdMatchesBufferHubBufferId) { std::unique_ptr b1 = - BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, + BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, kTestUsage, /*userMetadataSize=*/0); EXPECT_NE(b1, nullptr); - EXPECT_TRUE(b1->IsValid()); + EXPECT_TRUE(b1->isValid()); int b1_id = b1->id(); EXPECT_GE(b1_id, 0); diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp index 527a27d5dd..27ab0242ad 100644 --- a/libs/vr/libbufferhub/buffer_hub-test.cpp +++ b/libs/vr/libbufferhub/buffer_hub-test.cpp @@ -20,12 +20,12 @@ namespace { return result; \ })() -using android::BufferHubDefs::AnyClientAcquired; -using android::BufferHubDefs::AnyClientGained; -using android::BufferHubDefs::AnyClientPosted; -using android::BufferHubDefs::IsClientAcquired; -using android::BufferHubDefs::IsClientPosted; -using android::BufferHubDefs::IsClientReleased; +using android::BufferHubDefs::isAnyClientAcquired; +using android::BufferHubDefs::isAnyClientGained; +using android::BufferHubDefs::isAnyClientPosted; +using android::BufferHubDefs::isClientAcquired; +using android::BufferHubDefs::isClientPosted; +using android::BufferHubDefs::isClientReleased; using android::BufferHubDefs::kFirstClientBitMask; using android::dvr::ConsumerBuffer; using android::dvr::ProducerBuffer; @@ -268,7 +268,7 @@ TEST_F(LibBufferHubTest, TestAsyncStateTransitions) { // Post in gained state should succeed. EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); EXPECT_EQ(p->buffer_state(), c->buffer_state()); - EXPECT_TRUE(AnyClientPosted(p->buffer_state())); + EXPECT_TRUE(isAnyClientPosted(p->buffer_state())); // Post and gain in posted state should fail. EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence)); @@ -280,7 +280,7 @@ TEST_F(LibBufferHubTest, TestAsyncStateTransitions) { EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence)); EXPECT_FALSE(invalid_fence.IsValid()); EXPECT_EQ(p->buffer_state(), c->buffer_state()); - EXPECT_TRUE(AnyClientAcquired(p->buffer_state())); + EXPECT_TRUE(isAnyClientAcquired(p->buffer_state())); // Acquire, post, and gain in acquired state should fail. EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence)); @@ -304,7 +304,7 @@ TEST_F(LibBufferHubTest, TestAsyncStateTransitions) { EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence)); EXPECT_FALSE(invalid_fence.IsValid()); EXPECT_EQ(p->buffer_state(), c->buffer_state()); - EXPECT_TRUE(AnyClientGained(p->buffer_state())); + EXPECT_TRUE(isAnyClientGained(p->buffer_state())); // Acquire and gain in gained state should fail. EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence)); @@ -329,7 +329,7 @@ TEST_F(LibBufferHubTest, TestGainPostedBuffer) { ASSERT_TRUE(c.get() != nullptr); ASSERT_EQ(0, p->GainAsync()); ASSERT_EQ(0, p->Post(LocalHandle())); - ASSERT_TRUE(AnyClientPosted(p->buffer_state())); + ASSERT_TRUE(isAnyClientPosted(p->buffer_state())); // Gain in posted state should only succeed with gain_posted_buffer = true. LocalHandle invalid_fence; @@ -346,7 +346,7 @@ TEST_F(LibBufferHubTest, TestGainPostedBufferAsync) { ASSERT_TRUE(c.get() != nullptr); ASSERT_EQ(0, p->GainAsync()); ASSERT_EQ(0, p->Post(LocalHandle())); - ASSERT_TRUE(AnyClientPosted(p->buffer_state())); + ASSERT_TRUE(isAnyClientPosted(p->buffer_state())); // GainAsync in posted state should only succeed with gain_posted_buffer // equals true. @@ -364,9 +364,9 @@ TEST_F(LibBufferHubTest, TestGainPostedBuffer_noConsumer) { ASSERT_EQ(0, p->Post(LocalHandle())); // Producer state bit is in released state after post, other clients shall be // in posted state although there is no consumer of this buffer yet. - ASSERT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask())); + ASSERT_TRUE(isClientReleased(p->buffer_state(), p->client_state_mask())); ASSERT_TRUE(p->is_released()); - ASSERT_TRUE(AnyClientPosted(p->buffer_state())); + ASSERT_TRUE(isAnyClientPosted(p->buffer_state())); // Gain in released state should succeed. LocalHandle invalid_fence; @@ -393,14 +393,14 @@ TEST_F(LibBufferHubTest, TestMaxConsumers) { // Post the producer should trigger all consumers to be available. EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask())); + EXPECT_TRUE(isClientReleased(p->buffer_state(), p->client_state_mask())); for (size_t i = 0; i < kMaxConsumerCount; ++i) { EXPECT_TRUE( - IsClientPosted(cs[i]->buffer_state(), cs[i]->client_state_mask())); + isClientPosted(cs[i]->buffer_state(), cs[i]->client_state_mask())); EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(cs[i]))); EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence)); EXPECT_TRUE( - IsClientAcquired(p->buffer_state(), cs[i]->client_state_mask())); + isClientAcquired(p->buffer_state(), cs[i]->client_state_mask())); } // All consumers have to release before the buffer is considered to be @@ -424,22 +424,22 @@ TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) { kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); ASSERT_TRUE(p.get() != nullptr); EXPECT_EQ(0, p->GainAsync()); - EXPECT_TRUE(AnyClientGained(p->buffer_state())); + EXPECT_TRUE(isAnyClientGained(p->buffer_state())); std::unique_ptr c = ConsumerBuffer::Import(p->CreateConsumer()); ASSERT_TRUE(c.get() != nullptr); - EXPECT_TRUE(AnyClientGained(c->buffer_state())); + EXPECT_TRUE(isAnyClientGained(c->buffer_state())); DvrNativeBufferMetadata metadata; LocalHandle invalid_fence; // Post the gained buffer should signal already created consumer. EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_TRUE(AnyClientPosted(p->buffer_state())); + EXPECT_TRUE(isAnyClientPosted(p->buffer_state())); EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c))); EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_TRUE(AnyClientAcquired(c->buffer_state())); + EXPECT_TRUE(isAnyClientAcquired(c->buffer_state())); } TEST_F(LibBufferHubTest, TestCreateTheFirstConsumerAfterPostingBuffer) { @@ -447,7 +447,7 @@ TEST_F(LibBufferHubTest, TestCreateTheFirstConsumerAfterPostingBuffer) { kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); ASSERT_TRUE(p.get() != nullptr); EXPECT_EQ(0, p->GainAsync()); - EXPECT_TRUE(AnyClientGained(p->buffer_state())); + EXPECT_TRUE(isAnyClientGained(p->buffer_state())); DvrNativeBufferMetadata metadata; LocalHandle invalid_fence; @@ -462,7 +462,7 @@ TEST_F(LibBufferHubTest, TestCreateTheFirstConsumerAfterPostingBuffer) { std::unique_ptr c = ConsumerBuffer::Import(p->CreateConsumer()); ASSERT_TRUE(c.get() != nullptr); - EXPECT_TRUE(IsClientPosted(c->buffer_state(), c->client_state_mask())); + EXPECT_TRUE(isClientPosted(c->buffer_state(), c->client_state_mask())); EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence)); } @@ -500,7 +500,7 @@ TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) { EXPECT_TRUE(p->is_released()); EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence)); - EXPECT_TRUE(AnyClientGained(p->buffer_state())); + EXPECT_TRUE(isAnyClientGained(p->buffer_state())); } TEST_F(LibBufferHubTest, TestWithCustomMetadata) { diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp index b6ca64eef2..115e8666e5 100644 --- a/libs/vr/libbufferhub/consumer_buffer.cpp +++ b/libs/vr/libbufferhub/consumer_buffer.cpp @@ -38,7 +38,7 @@ int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta, // The buffer can be acquired iff the buffer state for this client is posted. uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::IsClientPosted(current_buffer_state, + if (!BufferHubDefs::isClientPosted(current_buffer_state, client_state_mask())) { ALOGE( "%s: Failed to acquire the buffer. The buffer is not posted, id=%d " @@ -58,7 +58,7 @@ int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta, " when trying to acquire the buffer and modify the buffer state to " "%" PRIx32 ". About to try again if the buffer is still posted.", __FUNCTION__, current_buffer_state, updated_buffer_state); - if (!BufferHubDefs::IsClientPosted(current_buffer_state, + if (!BufferHubDefs::isClientPosted(current_buffer_state, client_state_mask())) { ALOGE( "%s: Failed to acquire the buffer. The buffer is no longer posted, " @@ -144,7 +144,7 @@ int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta, // released state. uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire); - if (BufferHubDefs::IsClientReleased(current_buffer_state, + if (BufferHubDefs::isClientReleased(current_buffer_state, client_state_mask())) { return 0; } diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h index bab7367caa..e610e18849 100644 --- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h +++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h @@ -27,38 +27,38 @@ static constexpr uint32_t kHighBitsMask = android::BufferHubDefs::kHighBitsMask; static constexpr uint32_t kFirstClientBitMask = android::BufferHubDefs::kFirstClientBitMask; -static inline bool AnyClientGained(uint32_t state) { - return android::BufferHubDefs::AnyClientGained(state); +static inline bool isAnyClientGained(uint32_t state) { + return android::BufferHubDefs::isAnyClientGained(state); } -static inline bool IsClientGained(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::IsClientGained(state, client_bit_mask); +static inline bool isClientGained(uint32_t state, uint32_t client_bit_mask) { + return android::BufferHubDefs::isClientGained(state, client_bit_mask); } -static inline bool AnyClientPosted(uint32_t state) { - return android::BufferHubDefs::AnyClientPosted(state); +static inline bool isAnyClientPosted(uint32_t state) { + return android::BufferHubDefs::isAnyClientPosted(state); } -static inline bool IsClientPosted(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::IsClientPosted(state, client_bit_mask); +static inline bool isClientPosted(uint32_t state, uint32_t client_bit_mask) { + return android::BufferHubDefs::isClientPosted(state, client_bit_mask); } -static inline bool AnyClientAcquired(uint32_t state) { - return android::BufferHubDefs::AnyClientAcquired(state); +static inline bool isAnyClientAcquired(uint32_t state) { + return android::BufferHubDefs::isAnyClientAcquired(state); } -static inline bool IsClientAcquired(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::IsClientAcquired(state, client_bit_mask); +static inline bool isClientAcquired(uint32_t state, uint32_t client_bit_mask) { + return android::BufferHubDefs::isClientAcquired(state, client_bit_mask); } -static inline bool IsClientReleased(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::IsClientReleased(state, client_bit_mask); +static inline bool isClientReleased(uint32_t state, uint32_t client_bit_mask) { + return android::BufferHubDefs::isClientReleased(state, client_bit_mask); } // Returns the next available buffer client's client_state_masks. // @params union_bits. Union of all existing clients' client_state_masks. -static inline uint32_t FindNextAvailableClientStateMask(uint32_t union_bits) { - return android::BufferHubDefs::FindNextAvailableClientStateMask(union_bits); +static inline uint32_t findNextAvailableClientStateMask(uint32_t union_bits) { + return android::BufferHubDefs::findNextAvailableClientStateMask(union_bits); } using MetadataHeader = android::BufferHubDefs::MetadataHeader; diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp index edfdddf363..3d88ba5dbe 100644 --- a/libs/vr/libbufferhub/producer_buffer.cpp +++ b/libs/vr/libbufferhub/producer_buffer.cpp @@ -82,7 +82,7 @@ int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta, // The buffer can be posted iff the buffer state for this client is gained. uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::IsClientGained(current_buffer_state, + if (!BufferHubDefs::isClientGained(current_buffer_state, client_state_mask())) { ALOGE("%s: not gained, id=%d state=%" PRIx32 ".", __FUNCTION__, id(), current_buffer_state); @@ -103,7 +103,7 @@ int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta, "%" PRIx32 ". About to try again if the buffer is still gained by this client.", __FUNCTION__, current_buffer_state, updated_buffer_state); - if (!BufferHubDefs::IsClientGained(current_buffer_state, + if (!BufferHubDefs::isClientGained(current_buffer_state, client_state_mask())) { ALOGE( "%s: Failed to post the buffer. The buffer is no longer gained, " @@ -166,14 +166,14 @@ int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta, ALOGD_IF(TRACE, "%s: buffer=%d, state=%" PRIx32 ".", __FUNCTION__, id(), current_buffer_state); - if (BufferHubDefs::IsClientGained(current_buffer_state, + if (BufferHubDefs::isClientGained(current_buffer_state, client_state_mask())) { ALOGV("%s: already gained id=%d.", __FUNCTION__, id()); return 0; } - if (BufferHubDefs::AnyClientAcquired(current_buffer_state) || - BufferHubDefs::AnyClientGained(current_buffer_state) || - (BufferHubDefs::AnyClientPosted( + if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) || + BufferHubDefs::isAnyClientGained(current_buffer_state) || + (BufferHubDefs::isAnyClientPosted( current_buffer_state & active_clients_bit_mask_->load(std::memory_order_acquire)) && !gain_posted_buffer)) { @@ -195,9 +195,9 @@ int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta, "clients.", __FUNCTION__, current_buffer_state, updated_buffer_state); - if (BufferHubDefs::AnyClientAcquired(current_buffer_state) || - BufferHubDefs::AnyClientGained(current_buffer_state) || - (BufferHubDefs::AnyClientPosted( + if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) || + BufferHubDefs::isAnyClientGained(current_buffer_state) || + (BufferHubDefs::isAnyClientPosted( current_buffer_state & active_clients_bit_mask_->load(std::memory_order_acquire)) && !gain_posted_buffer)) { @@ -291,7 +291,7 @@ Status ProducerBuffer::Detach() { // TODO(b/112338294) Keep here for reference. Remove it after new logic is // written. /* uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::IsClientGained( + if (!BufferHubDefs::isClientGained( buffer_state, BufferHubDefs::kFirstClientStateMask)) { // Can only detach a ProducerBuffer when it's in gained state. ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx32 diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp index d7833f382b..2d3fa4aec0 100644 --- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp +++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp @@ -532,7 +532,7 @@ Status ProducerQueue::AddBuffer( Status ProducerQueue::InsertBuffer( const std::shared_ptr& buffer) { if (buffer == nullptr || - !BufferHubDefs::IsClientGained(buffer->buffer_state(), + !BufferHubDefs::isClientGained(buffer->buffer_state(), buffer->client_state_mask())) { ALOGE( "ProducerQueue::InsertBuffer: Can only insert a buffer when it's in " @@ -638,7 +638,7 @@ Status> ProducerQueue::DequeueUnacquiredBuffer( static_cast(*slot)); return ErrorStatus(EIO); } - if (!BufferHubDefs::AnyClientAcquired(buffer->buffer_state())) { + if (!BufferHubDefs::isAnyClientAcquired(buffer->buffer_state())) { *slot = *iter; unavailable_buffers_slot_.erase(iter); unavailable_buffers_slot_.push_back(*slot); diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp index 6b802fbf83..90ac1c2535 100644 --- a/services/bufferhub/BufferHubService.cpp +++ b/services/bufferhub/BufferHubService.cpp @@ -53,7 +53,7 @@ Return BufferHubService::allocateBuffer(const HardwareBufferDescription& d std::make_shared(desc.width, desc.height, desc.layers, desc.format, desc.usage, userMetadataSize, BufferHubIdGenerator::getInstance().getId()); - if (node == nullptr || !node->IsValid()) { + if (node == nullptr || !node->isValid()) { ALOGE("%s: creating BufferNode failed.", __FUNCTION__); _hidl_cb(/*status=*/BufferHubStatus::ALLOCATION_FAILED, /*bufferClient=*/nullptr, /*bufferTraits=*/{}); @@ -70,11 +70,11 @@ Return BufferHubService::allocateBuffer(const HardwareBufferDescription& d NATIVE_HANDLE_DECLARE_STORAGE(bufferInfoStorage, BufferHubDefs::kBufferInfoNumFds, BufferHubDefs::kBufferInfoNumInts); hidl_handle bufferInfo = - buildBufferInfo(bufferInfoStorage, node->id(), node->AddNewActiveClientsBitToMask(), - node->user_metadata_size(), node->metadata().ashmem_fd(), + buildBufferInfo(bufferInfoStorage, node->id(), node->addNewActiveClientsBitToMask(), + node->userMetadataSize(), node->metadata().ashmemFd(), node->eventFd().get()); BufferTraits bufferTraits = {/*bufferDesc=*/description, - /*bufferHandle=*/hidl_handle(node->buffer_handle()), + /*bufferHandle=*/hidl_handle(node->bufferHandle()), /*bufferInfo=*/std::move(bufferInfo)}; _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client, @@ -141,7 +141,7 @@ Return BufferHubService::importBuffer(const hidl_handle& tokenHandle, } sp client = new BufferClient(*originClient); - uint32_t clientStateMask = client->getBufferNode()->AddNewActiveClientsBitToMask(); + uint32_t clientStateMask = client->getBufferNode()->addNewActiveClientsBitToMask(); if (clientStateMask == 0U) { // Reach max client count ALOGE("%s: import failed, BufferNode#%u reached maximum clients.", __FUNCTION__, @@ -157,17 +157,17 @@ Return BufferHubService::importBuffer(const hidl_handle& tokenHandle, std::shared_ptr node = client->getBufferNode(); HardwareBufferDescription bufferDesc; - memcpy(&bufferDesc, &node->buffer_desc(), sizeof(HardwareBufferDescription)); + memcpy(&bufferDesc, &node->bufferDesc(), sizeof(HardwareBufferDescription)); // Allocate memory for bufferInfo of type hidl_handle on the stack. See // http://aosp/286282 for the usage of NATIVE_HANDLE_DECLARE_STORAGE. NATIVE_HANDLE_DECLARE_STORAGE(bufferInfoStorage, BufferHubDefs::kBufferInfoNumFds, BufferHubDefs::kBufferInfoNumInts); hidl_handle bufferInfo = buildBufferInfo(bufferInfoStorage, node->id(), clientStateMask, - node->user_metadata_size(), - node->metadata().ashmem_fd(), node->eventFd().get()); + node->userMetadataSize(), node->metadata().ashmemFd(), + node->eventFd().get()); BufferTraits bufferTraits = {/*bufferDesc=*/bufferDesc, - /*bufferHandle=*/hidl_handle(node->buffer_handle()), + /*bufferHandle=*/hidl_handle(node->bufferHandle()), /*bufferInfo=*/std::move(bufferInfo)}; _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client, @@ -231,10 +231,10 @@ Return BufferHubService::debug(const hidl_handle& fd, const hidl_vec node = std::move(iter->second.first); const uint32_t clientCount = iter->second.second; - AHardwareBuffer_Desc desc = node->buffer_desc(); + AHardwareBuffer_Desc desc = node->bufferDesc(); MetadataHeader* metadataHeader = - const_cast(&node->metadata())->metadata_header(); + const_cast(&node->metadata())->metadataHeader(); const uint32_t state = metadataHeader->buffer_state.load(std::memory_order_acquire); const uint64_t index = metadataHeader->queue_index; diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp index dfa2de0173..4f877b264a 100644 --- a/services/bufferhub/BufferNode.cpp +++ b/services/bufferhub/BufferNode.cpp @@ -11,10 +11,10 @@ namespace bufferhub { namespace V1_0 { namespace implementation { -void BufferNode::InitializeMetadata() { +void BufferNode::initializeMetadata() { // Using placement new here to reuse shared memory instead of new allocation // Initialize the atomic variables to zero. - BufferHubDefs::MetadataHeader* metadataHeader = mMetadata.metadata_header(); + BufferHubDefs::MetadataHeader* metadataHeader = mMetadata.metadataHeader(); mBufferState = new (&metadataHeader->buffer_state) std::atomic(0); mFenceState = new (&metadataHeader->fence_state) std::atomic(0); mActiveClientsBitMask = new (&metadataHeader->active_clients_bit_mask) std::atomic(0); @@ -54,12 +54,12 @@ BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, ui mBufferDesc.usage = usage; mBufferDesc.stride = out_stride; - mMetadata = BufferHubMetadata::Create(user_metadata_size); - if (!mMetadata.IsValid()) { + mMetadata = BufferHubMetadata::create(user_metadata_size); + if (!mMetadata.isValid()) { ALOGE("%s: Failed to allocate metadata.", __FUNCTION__); return; } - InitializeMetadata(); + initializeMetadata(); } BufferNode::~BufferNode() { @@ -77,17 +77,17 @@ BufferNode::~BufferNode() { } } -uint32_t BufferNode::GetActiveClientsBitMask() const { +uint32_t BufferNode::getActiveClientsBitMask() const { return mActiveClientsBitMask->load(std::memory_order_acquire); } -uint32_t BufferNode::AddNewActiveClientsBitToMask() { - uint32_t currentActiveClientsBitMask = GetActiveClientsBitMask(); +uint32_t BufferNode::addNewActiveClientsBitToMask() { + uint32_t currentActiveClientsBitMask = getActiveClientsBitMask(); uint32_t client_state_mask = 0U; uint32_t updatedActiveClientsBitMask = 0U; do { client_state_mask = - BufferHubDefs::FindNextAvailableClientStateMask(currentActiveClientsBitMask); + BufferHubDefs::findNextAvailableClientStateMask(currentActiveClientsBitMask); if (client_state_mask == 0U) { ALOGE("%s: reached the maximum number of channels per buffer node: %d.", __FUNCTION__, BufferHubDefs::kMaxNumberOfClients); @@ -102,7 +102,7 @@ uint32_t BufferNode::AddNewActiveClientsBitToMask() { return client_state_mask; } -void BufferNode::RemoveClientsBitFromMask(const uint32_t& value) { +void BufferNode::removeClientsBitFromMask(const uint32_t& value) { mActiveClientsBitMask->fetch_and(~value); } diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h index 112a21c9af..04970fd14d 100644 --- a/services/bufferhub/include/bufferhub/BufferNode.h +++ b/services/bufferhub/include/bufferhub/BufferNode.h @@ -22,15 +22,15 @@ public: ~BufferNode(); // Returns whether the object holds a valid metadata. - bool IsValid() const { return mMetadata.IsValid(); } + bool isValid() const { return mMetadata.isValid(); } int id() const { return mId; } - size_t user_metadata_size() const { return mMetadata.user_metadata_size(); } + size_t userMetadataSize() const { return mMetadata.userMetadataSize(); } // Accessors of the buffer description and handle - const native_handle_t* buffer_handle() const { return mBufferHandle; } - const AHardwareBuffer_Desc& buffer_desc() const { return mBufferDesc; } + const native_handle_t* bufferHandle() const { return mBufferHandle; } + const AHardwareBuffer_Desc& bufferDesc() const { return mBufferDesc; } // Accessor of event fd. const BufferHubEventFd& eventFd() const { return mEventFd; } @@ -41,24 +41,24 @@ public: // Gets the current value of mActiveClientsBitMask in mMetadata with // std::memory_order_acquire, so that all previous releases of // mActiveClientsBitMask from all threads will be returned here. - uint32_t GetActiveClientsBitMask() const; + uint32_t getActiveClientsBitMask() const; // Find and add a new client state mask to mActiveClientsBitMask in // mMetadata. // Return the new client state mask that is added to mActiveClientsBitMask. // Return 0U if there are already 16 clients of the buffer. - uint32_t AddNewActiveClientsBitToMask(); + uint32_t addNewActiveClientsBitToMask(); // Removes the value from active_clients_bit_mask in mMetadata with // std::memory_order_release, so that the change will be visible to any // acquire of mActiveClientsBitMask in any threads after the succeed of // this operation. - void RemoveClientsBitFromMask(const uint32_t& value); + void removeClientsBitFromMask(const uint32_t& value); private: // Helper method for constructors to initialize atomic metadata header // variables in shared memory. - void InitializeMetadata(); + void initializeMetadata(); // Gralloc buffer handles. native_handle_t* mBufferHandle; diff --git a/services/bufferhub/tests/BufferNode_test.cpp b/services/bufferhub/tests/BufferNode_test.cpp index ccb1197498..b9f1c81c63 100644 --- a/services/bufferhub/tests/BufferNode_test.cpp +++ b/services/bufferhub/tests/BufferNode_test.cpp @@ -28,7 +28,7 @@ protected: void SetUp() override { buffer_node = new BufferNode(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); - ASSERT_TRUE(buffer_node->IsValid()); + ASSERT_TRUE(buffer_node->isValid()); } void TearDown() override { @@ -41,65 +41,64 @@ protected: }; TEST_F(BufferNodeTest, TestCreateBufferNode) { - EXPECT_EQ(buffer_node->user_metadata_size(), kUserMetadataSize); + EXPECT_EQ(buffer_node->userMetadataSize(), kUserMetadataSize); // Test the handle just allocated is good (i.e. able to be imported) GraphicBufferMapper& mapper = GraphicBufferMapper::get(); const native_handle_t* outHandle; status_t ret = - mapper.importBuffer(buffer_node->buffer_handle(), buffer_node->buffer_desc().width, - buffer_node->buffer_desc().height, - buffer_node->buffer_desc().layers, - buffer_node->buffer_desc().format, buffer_node->buffer_desc().usage, - buffer_node->buffer_desc().stride, &outHandle); + mapper.importBuffer(buffer_node->bufferHandle(), buffer_node->bufferDesc().width, + buffer_node->bufferDesc().height, buffer_node->bufferDesc().layers, + buffer_node->bufferDesc().format, buffer_node->bufferDesc().usage, + buffer_node->bufferDesc().stride, &outHandle); EXPECT_EQ(ret, OK); EXPECT_THAT(outHandle, NotNull()); } -TEST_F(BufferNodeTest, TestAddNewActiveClientsBitToMask_twoNewClients) { - uint32_t new_client_state_mask_1 = buffer_node->AddNewActiveClientsBitToMask(); - EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), new_client_state_mask_1); +TEST_F(BufferNodeTest, TestaddNewActiveClientsBitToMask_twoNewClients) { + uint32_t new_client_state_mask_1 = buffer_node->addNewActiveClientsBitToMask(); + EXPECT_EQ(buffer_node->getActiveClientsBitMask(), new_client_state_mask_1); // Request and add a new client_state_mask again. // Active clients bit mask should be the union of the two new // client_state_masks. - uint32_t new_client_state_mask_2 = buffer_node->AddNewActiveClientsBitToMask(); - EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), + uint32_t new_client_state_mask_2 = buffer_node->addNewActiveClientsBitToMask(); + EXPECT_EQ(buffer_node->getActiveClientsBitMask(), new_client_state_mask_1 | new_client_state_mask_2); } -TEST_F(BufferNodeTest, TestAddNewActiveClientsBitToMask_32NewClients) { +TEST_F(BufferNodeTest, TestaddNewActiveClientsBitToMask_32NewClients) { uint32_t new_client_state_mask = 0U; uint32_t current_mask = 0U; uint32_t expected_mask = 0U; for (int i = 0; i < BufferHubDefs::kMaxNumberOfClients; ++i) { - new_client_state_mask = buffer_node->AddNewActiveClientsBitToMask(); + new_client_state_mask = buffer_node->addNewActiveClientsBitToMask(); EXPECT_NE(new_client_state_mask, 0U); EXPECT_FALSE(new_client_state_mask & current_mask); expected_mask = current_mask | new_client_state_mask; - current_mask = buffer_node->GetActiveClientsBitMask(); + current_mask = buffer_node->getActiveClientsBitMask(); EXPECT_EQ(current_mask, expected_mask); } // Method should fail upon requesting for more than maximum allowable clients. - new_client_state_mask = buffer_node->AddNewActiveClientsBitToMask(); + new_client_state_mask = buffer_node->addNewActiveClientsBitToMask(); EXPECT_EQ(new_client_state_mask, 0U); EXPECT_EQ(errno, E2BIG); } TEST_F(BufferNodeTest, TestRemoveActiveClientsBitFromMask) { - buffer_node->AddNewActiveClientsBitToMask(); - uint32_t current_mask = buffer_node->GetActiveClientsBitMask(); - uint32_t new_client_state_mask = buffer_node->AddNewActiveClientsBitToMask(); - EXPECT_NE(buffer_node->GetActiveClientsBitMask(), current_mask); + buffer_node->addNewActiveClientsBitToMask(); + uint32_t current_mask = buffer_node->getActiveClientsBitMask(); + uint32_t new_client_state_mask = buffer_node->addNewActiveClientsBitToMask(); + EXPECT_NE(buffer_node->getActiveClientsBitMask(), current_mask); - buffer_node->RemoveClientsBitFromMask(new_client_state_mask); - EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), current_mask); + buffer_node->removeClientsBitFromMask(new_client_state_mask); + EXPECT_EQ(buffer_node->getActiveClientsBitMask(), current_mask); // Remove the test_mask again to the active client bit mask should not modify // the value of active clients bit mask. - buffer_node->RemoveClientsBitFromMask(new_client_state_mask); - EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), current_mask); + buffer_node->removeClientsBitFromMask(new_client_state_mask); + EXPECT_EQ(buffer_node->getActiveClientsBitMask(), current_mask); } } // namespace diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp index 164d9e6b19..f3e54a0ed2 100644 --- a/services/vr/bufferhubd/producer_channel.cpp +++ b/services/vr/bufferhubd/producer_channel.cpp @@ -253,7 +253,7 @@ Status ProducerChannel::CreateConsumerStateMask() { uint32_t current_active_clients_bit_mask = active_clients_bit_mask_->load(std::memory_order_acquire); uint32_t consumer_state_mask = - BufferHubDefs::FindNextAvailableClientStateMask( + BufferHubDefs::findNextAvailableClientStateMask( current_active_clients_bit_mask | orphaned_consumer_bit_mask_); if (consumer_state_mask == 0U) { ALOGE("%s: reached the maximum mumber of consumers per producer: 63.", @@ -279,7 +279,7 @@ Status ProducerChannel::CreateConsumerStateMask() { "condition.", __FUNCTION__, updated_active_clients_bit_mask, current_active_clients_bit_mask); - consumer_state_mask = BufferHubDefs::FindNextAvailableClientStateMask( + consumer_state_mask = BufferHubDefs::findNextAvailableClientStateMask( current_active_clients_bit_mask | orphaned_consumer_bit_mask_); if (consumer_state_mask == 0U) { ALOGE("%s: reached the maximum mumber of consumers per producer: %d.", @@ -337,13 +337,13 @@ Status ProducerChannel::CreateConsumer( // consumer to a buffer that is available to producer (a.k.a a fully-released // buffer) or a gained buffer. if (current_buffer_state == 0U || - BufferHubDefs::AnyClientGained(current_buffer_state)) { + BufferHubDefs::isAnyClientGained(current_buffer_state)) { return {status.take()}; } // Signal the new consumer when adding it to a posted producer. bool update_buffer_state = true; - if (!BufferHubDefs::IsClientPosted(current_buffer_state, + if (!BufferHubDefs::isClientPosted(current_buffer_state, consumer_state_mask)) { uint32_t updated_buffer_state = current_buffer_state ^ @@ -360,7 +360,7 @@ Status ProducerChannel::CreateConsumer( "released.", __FUNCTION__, current_buffer_state, updated_buffer_state); if (current_buffer_state == 0U || - BufferHubDefs::AnyClientGained(current_buffer_state)) { + BufferHubDefs::isAnyClientGained(current_buffer_state)) { ALOGI("%s: buffer is gained or fully released, state=%" PRIx32 ".", __FUNCTION__, current_buffer_state); update_buffer_state = false; @@ -371,7 +371,7 @@ Status ProducerChannel::CreateConsumer( (consumer_state_mask & BufferHubDefs::kHighBitsMask); } } - if (update_buffer_state || BufferHubDefs::IsClientPosted( + if (update_buffer_state || BufferHubDefs::isClientPosted( buffer_state_->load(std::memory_order_acquire), consumer_state_mask)) { consumer->OnProducerPosted(); @@ -457,7 +457,7 @@ Status ProducerChannel::OnProducerGain(Message& /*message*/) { buffer_id()); uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::IsClientGained( + if (!BufferHubDefs::isClientGained( buffer_state, BufferHubDefs::kFirstClientStateMask)) { // Can only detach a ProducerBuffer when it's in gained state. ALOGW( @@ -616,9 +616,9 @@ void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) { const uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire); - if (BufferHubDefs::IsClientPosted(current_buffer_state, + if (BufferHubDefs::isClientPosted(current_buffer_state, consumer_state_mask) || - BufferHubDefs::IsClientAcquired(current_buffer_state, + BufferHubDefs::isClientAcquired(current_buffer_state, consumer_state_mask)) { // The consumer client is being destoryed without releasing. This could // happen in corner cases when the consumer crashes. Here we mark it @@ -627,9 +627,9 @@ void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) { return; } - if (BufferHubDefs::IsClientReleased(current_buffer_state, + if (BufferHubDefs::isClientReleased(current_buffer_state, consumer_state_mask) || - BufferHubDefs::AnyClientGained(current_buffer_state)) { + BufferHubDefs::isAnyClientGained(current_buffer_state)) { // The consumer is being close while it is suppose to signal a release // fence. Signal the dummy fence here. if (fence_state_->load(std::memory_order_acquire) & consumer_state_mask) { diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp index 6b33f5094c..004dc7cb4f 100644 --- a/services/vr/bufferhubd/producer_queue_channel.cpp +++ b/services/vr/bufferhubd/producer_queue_channel.cpp @@ -323,7 +323,7 @@ Status ProducerQueueChannel::OnProducerQueueInsertBuffer( // memory to indicate which client is the last producer of the buffer. // Currently, the first client is the only producer to the buffer. // Thus, it checks whether the first client gains the buffer below. - if (!BufferHubDefs::IsClientGained(buffer_state, + if (!BufferHubDefs::isClientGained(buffer_state, BufferHubDefs::kFirstClientBitMask)) { // Rejects the request if the requested buffer is not in Gained state. ALOGE( -- cgit v1.2.3-59-g8ed1b From 6338c9d00e5b80a379091d7b2c0d2ee8b0205afb Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Thu, 7 Feb 2019 16:57:51 -0800 Subject: Plumb fence from dequeueBuffer into renderengine This defers blocking from the ui thread, to the gpu driver, so SurfaceFlinger can continue work without waiting on an old frame. Bug: 123107664 Test: manual tests Change-Id: Ied4ba84dd3fe63c65470ae3396dec0cb667a5ff0 --- libs/renderengine/gl/GLESRenderEngine.cpp | 7 ++++++- libs/renderengine/gl/GLESRenderEngine.h | 3 ++- libs/renderengine/include/renderengine/RenderEngine.h | 7 +++++-- .../include/renderengine/mock/RenderEngine.h | 4 ++-- libs/renderengine/tests/RenderEngineTest.cpp | 3 ++- libs/ui/GraphicBuffer.cpp | 3 +++ .../include/compositionengine/RenderSurface.h | 2 +- .../include/compositionengine/impl/RenderSurface.h | 2 +- .../include/compositionengine/mock/RenderSurface.h | 2 +- .../CompositionEngine/src/RenderSurface.cpp | 17 ++++++++--------- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 3 ++- services/surfaceflinger/SurfaceFlinger.cpp | 12 +++++++----- .../surfaceflinger/tests/unittests/CompositionTest.cpp | 13 ++++++++----- 13 files changed, 48 insertions(+), 30 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 8f9071e6b8..e7ff9abe14 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -789,13 +789,18 @@ bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) { status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, ANativeWindowBuffer* const buffer, - base::unique_fd* drawFence) { + base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_CALL(); if (layers.empty()) { ALOGV("Drawing empty layer stack"); return NO_ERROR; } + if (bufferFence.get() >= 0 && !waitFence(std::move(bufferFence))) { + ATRACE_NAME("Waiting before draw"); + sync_wait(bufferFence.get(), -1); + } + BindNativeBufferAsFramebuffer fbo(*this, buffer); if (fbo.getStatus() != NO_ERROR) { diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 7b72666f02..a86b4f52ed 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -81,7 +81,8 @@ public: bool supportsProtectedContent() const override; bool useProtectedContext(bool useProtectedContext) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - ANativeWindowBuffer* buffer, base::unique_fd* drawFence) override; + ANativeWindowBuffer* buffer, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) override; // internal to RenderEngine EGLDisplay getEGLDisplay() const { return mEGLDisplay; } diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index b51ed22ef0..812d761987 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -167,7 +167,9 @@ public: // drawing any layers. // @param layers The layers to draw onto the display, in Z-order. // @param buffer The buffer which will be drawn to. This buffer will be - // ready once displayFence fires. + // ready once drawFence fires. + // @param bufferFence Fence signalling that the buffer is ready to be drawn + // to. // @param drawFence A pointer to a fence, which will fire when the buffer // has been drawn to and is ready to be examined. The fence will be // initialized by this method. The caller will be responsible for owning the @@ -176,7 +178,8 @@ public: // now, this always returns NO_ERROR. virtual status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - ANativeWindowBuffer* buffer, base::unique_fd* drawFence) = 0; + ANativeWindowBuffer* buffer, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) = 0; protected: // Gets a framebuffer to render to. This framebuffer may or may not be diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 800eac356e..5956c46c0b 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -78,9 +78,9 @@ public: MOCK_CONST_METHOD0(isProtected, bool()); MOCK_CONST_METHOD0(supportsProtectedContent, bool()); MOCK_METHOD1(useProtectedContext, bool(bool)); - MOCK_METHOD4(drawLayers, + MOCK_METHOD5(drawLayers, status_t(const DisplaySettings&, const std::vector&, - ANativeWindowBuffer*, base::unique_fd*)); + ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*)); }; } // namespace mock diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index f82beeb4c5..f28f6724d9 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -105,7 +105,8 @@ struct RenderEngineTest : public ::testing::Test { std::vector layers, sp buffer) { base::unique_fd fence; - status_t status = sRE->drawLayers(settings, layers, buffer->getNativeBuffer(), &fence); + status_t status = sRE->drawLayers(settings, layers, buffer->getNativeBuffer(), + base::unique_fd(), &fence); int fd = fence.release(); if (fd >= 0) { diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index f487dfa81b..79958ece9e 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -15,6 +15,7 @@ */ #define LOG_TAG "GraphicBuffer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS #include @@ -29,6 +30,7 @@ #include #include #include +#include namespace android { @@ -111,6 +113,7 @@ GraphicBuffer::GraphicBuffer(std::unique_ptr buffer) : GraphicB GraphicBuffer::~GraphicBuffer() { + ATRACE_CALL(); if (handle) { free_handle(); } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index 20093808cb..e69b99f0f5 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -71,7 +71,7 @@ public: virtual status_t prepareFrame() = 0; // Allocates a buffer as scratch space for GPU composition - virtual sp dequeueBuffer() = 0; + virtual sp dequeueBuffer(base::unique_fd* bufferFence) = 0; // Queues the drawn buffer for consumption by HWC. readyFence is the fence // which will fire when the buffer is ready for consumption. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index 58b13ed603..3c79084073 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -52,7 +52,7 @@ public: void setProtected(bool useProtected) override; status_t beginFrame(bool mustRecompose) override; status_t prepareFrame() override; - sp dequeueBuffer() override; + sp dequeueBuffer(base::unique_fd* bufferFence) override; void queueBuffer(base::unique_fd&& readyFence) override; void onPresentDisplayCompleted() override; void setViewportAndProjection() override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index 8442bef6fc..1562f58709 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -37,7 +37,7 @@ public: MOCK_METHOD1(setBufferDataspace, void(ui::Dataspace)); MOCK_METHOD1(beginFrame, status_t(bool mustRecompose)); MOCK_METHOD0(prepareFrame, status_t()); - MOCK_METHOD0(dequeueBuffer, sp()); + MOCK_METHOD1(dequeueBuffer, sp(base::unique_fd*)); MOCK_METHOD1(queueBuffer, void(base::unique_fd&&)); MOCK_METHOD0(onPresentDisplayCompleted, void()); MOCK_METHOD0(setViewportAndProjection, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index ebb1bc2e5b..b4dfba1d07 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + #include #include #include @@ -28,6 +30,7 @@ #include #include #include +#include #include "DisplayHardware/HWComposer.h" @@ -127,7 +130,8 @@ status_t RenderSurface::prepareFrame() { return mDisplaySurface->prepareFrame(compositionType); } -sp RenderSurface::dequeueBuffer() { +sp RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { + ATRACE_CALL(); int fd = -1; ANativeWindowBuffer* buffer = nullptr; @@ -145,13 +149,7 @@ sp RenderSurface::dequeueBuffer() { mGraphicBuffer->getNativeBuffer()->handle); mGraphicBuffer = GraphicBuffer::from(buffer); - // Block until the buffer is ready - // TODO(alecmouri): it's perhaps more appropriate to block renderengine so - // that the gl driver can block instead. - if (fd >= 0) { - sync_wait(fd, -1); - close(fd); - } + *bufferFence = base::unique_fd(fd); return mGraphicBuffer; } @@ -172,7 +170,8 @@ void RenderSurface::queueBuffer(base::unique_fd&& readyFence) { // We shouldn't deadlock here, since mGraphicBuffer == nullptr only // after a successful call to queueBuffer, or if dequeueBuffer has // never been called. - dequeueBuffer(); + base::unique_fd unused; + dequeueBuffer(&unused); } if (mGraphicBuffer == nullptr) { diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index 0a7c46254a..84af9b967e 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -358,7 +358,8 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { .WillOnce( DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR))); - EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer().get()); + base::unique_fd fence; + EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence).get()); EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index adc4a6164e..c624371d49 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3323,12 +3323,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, renderengine::DisplaySettings clientCompositionDisplay; std::vector clientCompositionLayers; sp buf; + base::unique_fd fd; if (hasClientComposition) { ALOGV("hasClientComposition"); - buf = display->getRenderSurface()->dequeueBuffer(); - + buf = display->getRenderSurface()->dequeueBuffer(&fd); if (buf == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", @@ -3349,7 +3349,6 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, m[3][0] = displayTransform[2][0]; m[3][1] = displayTransform[2][1]; m[3][3] = displayTransform[2][2]; - clientCompositionDisplay.globalTransform = m; const auto* profile = display->getDisplayColorProfile(); @@ -3449,7 +3448,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, } } getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers, - buf->getNativeBuffer(), readyFence); + buf->getNativeBuffer(), std::move(fd), readyFence); } return true; } @@ -5626,9 +5625,12 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, }); clientCompositionDisplay.clearRegion = clearRegion; + // Use an empty fence for the buffer fence, since we just created the buffer so + // there is no need for synchronization with the GPU. + base::unique_fd bufferFence; base::unique_fd drawFence; getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers, buffer, - &drawFence); + std::move(bufferFence), &drawFence); *outSyncFd = drawFence.release(); } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index d0f7b9036b..6deec2961e 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -312,7 +312,7 @@ struct BaseDisplayVariant { .WillRepeatedly( [](const renderengine::DisplaySettings& displaySettings, const std::vector& /*layerSettings*/, - ANativeWindowBuffer*, base::unique_fd*) -> status_t { + ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -351,7 +351,7 @@ struct BaseDisplayVariant { .WillRepeatedly( [](const renderengine::DisplaySettings& displaySettings, const std::vector& /*layerSettings*/, - ANativeWindowBuffer*, base::unique_fd*) -> status_t { + ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -580,7 +580,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - ANativeWindowBuffer*, base::unique_fd*) -> status_t { + ANativeWindowBuffer*, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -624,7 +625,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - ANativeWindowBuffer*, base::unique_fd*) -> status_t { + ANativeWindowBuffer*, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -693,7 +695,8 @@ struct SecureLayerProperties : public BaseLayerProperties EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - ANativeWindowBuffer*, base::unique_fd*) -> status_t { + ANativeWindowBuffer*, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); -- cgit v1.2.3-59-g8ed1b From e672cd0eef276d65293bb4baa573765534a2431d Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Thu, 14 Feb 2019 16:01:29 -0800 Subject: Implement converters for bufferqueue@2.0 Test: make cts -j123 && cts-tradefed run cts-dev -m \ CtsMediaTestCases --compatibility:module-arg \ CtsMediaTestCases:include-annotation:\ android.platform.test.annotations.RequiresDevice Bug: 112508112 Change-Id: I60f2068788136b01c45e03fc4d846d4e37edc7f2 --- libs/gui/Android.bp | 75 +-- libs/gui/IGraphicBufferProducer.cpp | 15 +- libs/gui/IProducerListener.cpp | 22 +- libs/gui/bufferqueue/1.0/H2BProducerListener.cpp | 59 +++ .../bufferqueue/2.0/B2HGraphicBufferProducer.cpp | 331 +++++++++++++ libs/gui/bufferqueue/2.0/B2HProducerListener.cpp | 47 ++ .../bufferqueue/2.0/H2BGraphicBufferProducer.cpp | 514 +++++++++++++++++++++ libs/gui/bufferqueue/2.0/H2BProducerListener.cpp | 57 +++ libs/gui/bufferqueue/2.0/types.cpp | 301 ++++++++++++ libs/gui/include/gui/IGraphicBufferProducer.h | 15 +- libs/gui/include/gui/IProducerListener.h | 13 +- .../gui/bufferqueue/1.0/H2BProducerListener.h | 52 +++ .../gui/bufferqueue/2.0/B2HGraphicBufferProducer.h | 121 +++++ .../gui/bufferqueue/2.0/B2HProducerListener.h | 57 +++ .../gui/bufferqueue/2.0/H2BGraphicBufferProducer.h | 107 +++++ .../gui/bufferqueue/2.0/H2BProducerListener.h | 52 +++ libs/gui/include/gui/bufferqueue/2.0/types.h | 129 ++++++ libs/nativewindow/AHardwareBuffer.cpp | 6 +- libs/nativewindow/Android.bp | 2 +- libs/ui/Android.bp | 2 +- libs/ui/GraphicBuffer.cpp | 16 + libs/ui/include/ui/Fence.h | 6 + libs/ui/include/ui/GraphicBuffer.h | 5 + 23 files changed, 1936 insertions(+), 68 deletions(-) create mode 100644 libs/gui/bufferqueue/1.0/H2BProducerListener.cpp create mode 100644 libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp create mode 100644 libs/gui/bufferqueue/2.0/B2HProducerListener.cpp create mode 100644 libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp create mode 100644 libs/gui/bufferqueue/2.0/H2BProducerListener.cpp create mode 100644 libs/gui/bufferqueue/2.0/types.cpp create mode 100644 libs/gui/include/gui/bufferqueue/1.0/H2BProducerListener.h create mode 100644 libs/gui/include/gui/bufferqueue/2.0/B2HGraphicBufferProducer.h create mode 100644 libs/gui/include/gui/bufferqueue/2.0/B2HProducerListener.h create mode 100644 libs/gui/include/gui/bufferqueue/2.0/H2BGraphicBufferProducer.h create mode 100644 libs/gui/include/gui/bufferqueue/2.0/H2BProducerListener.h create mode 100644 libs/gui/include/gui/bufferqueue/2.0/types.h (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 8b663bc8ec..4c2e6532ff 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -31,44 +31,7 @@ cc_library_shared { "-Werror", ], cppflags: [ - "-Weverything", - - // The static constructors and destructors in this library have not been noted to - // introduce significant overheads - "-Wno-exit-time-destructors", - "-Wno-global-constructors", - - // We only care about compiling as C++14 - "-Wno-c++98-compat-pedantic", - - // We don't need to enumerate every case in a switch as long as a default case - // is present - "-Wno-switch-enum", - - // Allow calling variadic macros without a __VA_ARGS__ list - "-Wno-gnu-zero-variadic-macro-arguments", - - // Don't warn about struct padding - "-Wno-padded", - - // We are aware of the risks inherent in comparing floats for equality - "-Wno-float-equal", - - // Pure abstract classes trigger this warning - "-Wno-weak-vtables", - - // Allow four-character integer literals - "-Wno-four-char-constants", - - // Allow documentation warnings - "-Wno-documentation", - - // Allow implicit instantiation for templated class function - "-Wno-undefined-func-template", - - // Allow explicitly marking struct as packed even when unnecessary - "-Wno-packed", - + "-Wextra", "-DDEBUG_ONLY_CODE=0", ], @@ -121,30 +84,38 @@ cc_library_shared { "view/Surface.cpp", "bufferqueue/1.0/B2HProducerListener.cpp", "bufferqueue/1.0/H2BGraphicBufferProducer.cpp", + "bufferqueue/1.0/H2BProducerListener.cpp", + "bufferqueue/2.0/B2HGraphicBufferProducer.cpp", + "bufferqueue/2.0/B2HProducerListener.cpp", + "bufferqueue/2.0/H2BGraphicBufferProducer.cpp", + "bufferqueue/2.0/H2BProducerListener.cpp", + "bufferqueue/2.0/types.cpp", ], shared_libs: [ "android.frameworks.bufferhub@1.0", + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", "android.hardware.graphics.common@1.1", + "android.hardware.graphics.common@1.2", + "android.hidl.token@1.0-utils", "libbase", - "libsync", "libbinder", - "libhwbinder", "libbufferhub", "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui. - "libpdx_default_transport", "libcutils", "libEGL", "libGLESv2", - "libui", - "libutils", - "libnativewindow", - "liblog", - "libinput", "libhidlbase", "libhidltransport", - "android.hidl.token@1.0-utils", - "android.hardware.graphics.bufferqueue@1.0", + "libhwbinder", + "libinput", + "liblog", + "libnativewindow", + "libpdx_default_transport", + "libsync", + "libui", + "libutils", "libvndksupport", ], @@ -163,16 +134,16 @@ cc_library_shared { "android.frameworks.bufferhub@1.0", "libbufferhub", "libbufferhubqueue", - "libpdx_default_transport", "libinput", + "libpdx_default_transport", ], }, }, header_libs: [ "libdvr_headers", - "libnativebase_headers", "libgui_headers", + "libnativebase_headers", "libpdx_headers", ], @@ -181,9 +152,11 @@ cc_library_shared { "libEGL", "libnativewindow", "libui", - "android.hidl.token@1.0-utils", "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", "android.hardware.graphics.common@1.1", + "android.hardware.graphics.common@1.2", + "android.hidl.token@1.0-utils", ], export_header_lib_headers: [ diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 8907de4b5d..9dde15dd0e 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -30,16 +30,21 @@ #ifndef NO_BUFFERHUB #include #endif + +#include +#include #include #include #include -#include - namespace android { // ---------------------------------------------------------------------------- -using ::android::hardware::graphics::bufferqueue::V1_0::utils:: +using H2BGraphicBufferProducerV1_0 = + ::android::hardware::graphics::bufferqueue::V1_0::utils:: + H2BGraphicBufferProducer; +using H2BGraphicBufferProducerV2_0 = + ::android::hardware::graphics::bufferqueue::V2_0::utils:: H2BGraphicBufferProducer; enum { @@ -534,7 +539,9 @@ public: BpGraphicBufferProducer::~BpGraphicBufferProducer() {} class HpGraphicBufferProducer : public HpInterface< - BpGraphicBufferProducer, H2BGraphicBufferProducer> { + BpGraphicBufferProducer, + H2BGraphicBufferProducerV1_0, + H2BGraphicBufferProducerV2_0> { public: explicit HpGraphicBufferProducer(const sp& base) : PBase(base) {} diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp index 62abfa81c4..936063a5bd 100644 --- a/libs/gui/IProducerListener.cpp +++ b/libs/gui/IProducerListener.cpp @@ -15,7 +15,8 @@ */ #include - +#include +#include #include namespace android { @@ -61,7 +62,24 @@ public: // translation unit (see clang warning -Wweak-vtables) BpProducerListener::~BpProducerListener() {} -IMPLEMENT_META_INTERFACE(ProducerListener, "android.gui.IProducerListener") +class HpProducerListener : public HpInterface< + BpProducerListener, + hardware::graphics::bufferqueue::V1_0::utils::H2BProducerListener, + hardware::graphics::bufferqueue::V2_0::utils::H2BProducerListener> { +public: + explicit HpProducerListener(const sp& base) : PBase{base} {} + + virtual void onBufferReleased() override { + mBase->onBufferReleased(); + } + + virtual bool needsReleaseNotify() override { + return mBase->needsReleaseNotify(); + } +}; + +IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener, + "android.gui.IProducerListener") status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { diff --git a/libs/gui/bufferqueue/1.0/H2BProducerListener.cpp b/libs/gui/bufferqueue/1.0/H2BProducerListener.cpp new file mode 100644 index 0000000000..2712f42c89 --- /dev/null +++ b/libs/gui/bufferqueue/1.0/H2BProducerListener.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2019 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "H2BProducerListener@1.0" + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V1_0 { +namespace utils { + +using ::android::hardware::Return; + +H2BProducerListener::H2BProducerListener(sp const& base) + : CBase{base} { +} + +void H2BProducerListener::onBufferReleased() { + if (!mBase->onBufferReleased().isOk()) { + LOG(ERROR) << "onBufferReleased: transaction failed."; + } +} + +bool H2BProducerListener::needsReleaseNotify() { + Return transResult = mBase->needsReleaseNotify(); + if (!transResult.isOk()) { + LOG(ERROR) << "needsReleaseNotify: transaction failed."; + return false; + } + return static_cast(transResult); +} + +} // namespace utils +} // namespace V1_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + diff --git a/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp new file mode 100644 index 0000000000..e0395939e9 --- /dev/null +++ b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp @@ -0,0 +1,331 @@ +/* + * Copyright 2019 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "H2BGraphicBufferProducer@2.0" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +// B2HGraphicBufferProducer +// ======================== + +B2HGraphicBufferProducer::B2HGraphicBufferProducer( + sp const& base) + : mBase{base} { +} + +Return B2HGraphicBufferProducer::setMaxDequeuedBufferCount( + int32_t maxDequeuedBuffers) { + HStatus hStatus{}; + bool converted = b2h( + mBase->setMaxDequeuedBufferCount( + static_cast(maxDequeuedBuffers)), + &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::requestBuffer( + int32_t slot, + requestBuffer_cb _hidl_cb) { + sp bBuffer; + HStatus hStatus{}; + HardwareBuffer hBuffer{}; + uint32_t hGenerationNumber{}; + bool converted = + b2h(mBase->requestBuffer( + static_cast(slot), &bBuffer), + &hStatus) && + b2h(bBuffer, &hBuffer, &hGenerationNumber); + _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, + hBuffer, hGenerationNumber); + return {}; +} + +Return B2HGraphicBufferProducer::setAsyncMode(bool async) { + HStatus hStatus{}; + bool converted = b2h(mBase->setAsyncMode(async), &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::dequeueBuffer( + DequeueBufferInput const& input, + dequeueBuffer_cb _hidl_cb) { + int bSlot{}; + sp bFence; + HStatus hStatus{}; + DequeueBufferOutput hOutput{}; + HFenceWrapper hFenceWrapper; + bool converted = + b2h(mBase->dequeueBuffer( + &bSlot, + &bFence, + input.width, + input.height, + static_cast(input.format), + input.usage, + &hOutput.bufferAge, + nullptr /* outTimestamps */), + &hStatus, + &hOutput.bufferNeedsReallocation, + &hOutput.releaseAllBuffers) && + b2h(bFence, &hFenceWrapper); + hOutput.fence = hFenceWrapper.getHandle(); + _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, + static_cast(bSlot), + hOutput); + return {}; +} + +Return B2HGraphicBufferProducer::detachBuffer(int32_t slot) { + HStatus hStatus{}; + bool converted = b2h( + mBase->detachBuffer(static_cast(slot)), &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::detachNextBuffer( + detachNextBuffer_cb _hidl_cb) { + sp bBuffer; + sp bFence; + HStatus hStatus{}; + HardwareBuffer hBuffer{}; + HFenceWrapper hFenceWrapper; + bool converted = + b2h(mBase->detachNextBuffer(&bBuffer, &bFence), &hStatus) && + b2h(bBuffer, &hBuffer) && + b2h(bFence, &hFenceWrapper); + _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, + hBuffer, + hFenceWrapper.getHandle()); + return {}; +} + +Return B2HGraphicBufferProducer::attachBuffer( + HardwareBuffer const& hBuffer, + uint32_t generationNumber, + attachBuffer_cb _hidl_cb) { + sp bBuffer; + if (!h2b(hBuffer, &bBuffer) || !bBuffer) { + _hidl_cb(HStatus::UNKNOWN_ERROR, + static_cast(SlotIndex::INVALID), + false); + return {}; + } + bBuffer->setGenerationNumber(generationNumber); + + int bSlot{}; + HStatus hStatus{}; + bool releaseAllBuffers{}; + bool converted = b2h( + mBase->attachBuffer(&bSlot, bBuffer), &hStatus, + nullptr /* bufferNeedsReallocation */, + &releaseAllBuffers); + _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, + static_cast(bSlot), + releaseAllBuffers); + return {}; +} + +Return B2HGraphicBufferProducer::queueBuffer( + int32_t slot, + QueueBufferInput const& hInput, + queueBuffer_cb _hidl_cb) { + using HOutput = QueueBufferOutput; + using BInput = BGraphicBufferProducer::QueueBufferInput; + using BOutput = BGraphicBufferProducer::QueueBufferOutput; + + BInput bInput{ + hInput.timestamp, + hInput.isAutoTimestamp, + static_cast(hInput.dataSpace), + {}, /* crop */ + 0 /* scalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE */, + static_cast(hInput.transform), + {}, /* fence */ + static_cast(hInput.stickyTransform), + false /* getFrameTimestamps */}; + + // Convert crop. + if (!h2b(hInput.crop, &bInput.crop)) { + _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{}); + return {}; + } + + // Convert surfaceDamage. + if (!h2b(hInput.surfaceDamage, &bInput.surfaceDamage)) { + _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{}); + return {}; + } + + // Convert fence. + if (!h2b(hInput.fence, &bInput.fence)) { + _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{}); + return {}; + } + + BOutput bOutput{}; + HStatus hStatus{}; + bool converted = b2h( + mBase->queueBuffer(static_cast(slot), bInput, &bOutput), + &hStatus); + + _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, + HOutput{bOutput.width, + bOutput.height, + static_cast(bOutput.transformHint), + bOutput.numPendingBuffers, + bOutput.nextFrameNumber, + bOutput.bufferReplaced}); + return {}; +} + +Return B2HGraphicBufferProducer::cancelBuffer( + int32_t slot, + hidl_handle const& fence) { + sp bFence; + if (!h2b(fence.getNativeHandle(), &bFence)) { + return {HStatus::UNKNOWN_ERROR}; + } + HStatus hStatus{}; + bool converted = b2h( + mBase->cancelBuffer(static_cast(slot), bFence), + &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::query(int32_t what, query_cb _hidl_cb) { + int value{}; + int result = mBase->query(static_cast(what), &value); + _hidl_cb(static_cast(result), static_cast(value)); + return {}; +} + +Return B2HGraphicBufferProducer::connect( + sp const& hListener, + HConnectionType hConnectionType, + bool producerControlledByApp, + connect_cb _hidl_cb) { + using BOutput = BGraphicBufferProducer::QueueBufferOutput; + using HOutput = HGraphicBufferProducer::QueueBufferOutput; + sp bListener = new H2BProducerListener(hListener); + if (!bListener) { + _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{}); + return {}; + } + int bConnectionType; + if (!h2b(hConnectionType, &bConnectionType)) { + _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{}); + return {}; + } + BOutput bOutput{}; + HStatus hStatus{}; + bool converted = b2h( + mBase->connect(bListener, + bConnectionType, + producerControlledByApp, + &bOutput), + &hStatus); + _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, + HOutput{bOutput.width, + bOutput.height, + static_cast(bOutput.transformHint), + bOutput.numPendingBuffers, + bOutput.nextFrameNumber, + bOutput.bufferReplaced}); + return {}; +} + +Return B2HGraphicBufferProducer::disconnect( + HConnectionType hConnectionType) { + int bConnectionType; + if (!h2b(hConnectionType, &bConnectionType)) { + return {HStatus::UNKNOWN_ERROR}; + } + HStatus hStatus{}; + bool converted = b2h(mBase->disconnect(bConnectionType), &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::allocateBuffers( + uint32_t width, uint32_t height, + uint32_t format, uint64_t usage) { + mBase->allocateBuffers( + width, height, static_cast(format), usage); + return {HStatus::OK}; +} + +Return B2HGraphicBufferProducer::allowAllocation(bool allow) { + HStatus hStatus{}; + bool converted = b2h(mBase->allowAllocation(allow), &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::setGenerationNumber( + uint32_t generationNumber) { + HStatus hStatus{}; + bool converted = b2h( + mBase->setGenerationNumber(generationNumber), + &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::setDequeueTimeout( + int64_t timeoutNs) { + HStatus hStatus{}; + bool converted = b2h( + mBase->setDequeueTimeout(static_cast(timeoutNs)), + &hStatus); + return {converted ? hStatus : HStatus::UNKNOWN_ERROR}; +} + +Return B2HGraphicBufferProducer::getUniqueId() { + uint64_t outId{}; + HStatus hStatus{}; + bool converted = b2h(mBase->getUniqueId(&outId), &hStatus); + return {converted ? outId : 0}; +} + +Return B2HGraphicBufferProducer::getConsumerName( + getConsumerName_cb _hidl_cb) { + _hidl_cb(hidl_string{mBase->getConsumerName().c_str()}); + return {}; +} + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + diff --git a/libs/gui/bufferqueue/2.0/B2HProducerListener.cpp b/libs/gui/bufferqueue/2.0/B2HProducerListener.cpp new file mode 100644 index 0000000000..c4c96eba50 --- /dev/null +++ b/libs/gui/bufferqueue/2.0/B2HProducerListener.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2019 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 + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +// B2HProducerListener +B2HProducerListener::B2HProducerListener(sp const& base) + : mBase{base}, + mNeedsReleaseNotify{base ? base->needsReleaseNotify() : false} { +} + +Return B2HProducerListener::onBuffersReleased(uint32_t count) { + if (mNeedsReleaseNotify) { + for (; count > 0; --count) { + mBase->onBufferReleased(); + } + } + return {}; +} + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + diff --git a/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp new file mode 100644 index 0000000000..1023ef108a --- /dev/null +++ b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp @@ -0,0 +1,514 @@ +/* + * Copyright 2019 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "H2BGraphicBufferProducer@2.0" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +// H2BGraphicBufferProducer +// ======================== + +status_t H2BGraphicBufferProducer::requestBuffer(int slot, + sp* bBuffer) { + bool converted{}; + status_t bStatus{}; + Return transResult = mBase->requestBuffer(slot, + [&converted, &bStatus, bBuffer]( + HStatus hStatus, + HardwareBuffer const& hBuffer, + uint32_t generationNumber) { + converted = + h2b(hStatus, &bStatus) && + h2b(hBuffer, bBuffer); + if (*bBuffer) { + (*bBuffer)->setGenerationNumber(generationNumber); + } + }); + if (!transResult.isOk()) { + LOG(ERROR) << "requestBuffer: transaction failed."; + return FAILED_TRANSACTION; + } + if (!converted) { + LOG(ERROR) << "requestBuffer: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::setMaxDequeuedBufferCount( + int maxDequeuedBuffers) { + status_t bStatus{}; + Return transResult = mBase->setMaxDequeuedBufferCount( + static_cast(maxDequeuedBuffers)); + if (!transResult.isOk()) { + LOG(ERROR) << "setMaxDequeuedBufferCount: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "setMaxDequeuedBufferCount: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::setAsyncMode(bool async) { + status_t bStatus{}; + Return transResult = mBase->setAsyncMode(async); + if (!transResult.isOk()) { + LOG(ERROR) << "setAsyncMode: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "setAsyncMode: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::dequeueBuffer( + int* slot, sp* fence, + uint32_t w, uint32_t h, + PixelFormat format, uint64_t usage, + uint64_t* outBufferAge, FrameEventHistoryDelta* /* outTimestamps */) { + + using HInput = HGraphicBufferProducer::DequeueBufferInput; + HInput input{w, h, static_cast(format), usage}; + + using HOutput = HGraphicBufferProducer::DequeueBufferOutput; + bool converted{}; + status_t bStatus{}; + Return transResult = mBase->dequeueBuffer(input, + [&converted, &bStatus, slot, fence, outBufferAge] ( + HStatus hStatus, int32_t hSlot, HOutput const& hOutput) { + converted = h2b(hStatus, &bStatus); + if (!converted || bStatus != OK) { + return; + } + *slot = hSlot; + *outBufferAge = hOutput.bufferAge; + bStatus = + (hOutput.bufferNeedsReallocation ? + BUFFER_NEEDS_REALLOCATION : 0) | + (hOutput.releaseAllBuffers ? + RELEASE_ALL_BUFFERS : 0); + converted = h2b(hOutput.fence, fence); + }); + if (!transResult.isOk()) { + LOG(ERROR) << "dequeueBuffer: transaction failed."; + return FAILED_TRANSACTION; + } + if (!converted) { + LOG(ERROR) << "dequeueBuffer: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::detachBuffer(int slot) { + status_t bStatus{}; + Return transResult = mBase->detachBuffer( + static_cast(slot)); + if (!transResult.isOk()) { + LOG(ERROR) << "detachBuffer: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "detachBuffer: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::detachNextBuffer( + sp* outBuffer, sp* outFence) { + bool converted{}; + status_t bStatus{}; + Return transResult = mBase->detachNextBuffer( + [&converted, &bStatus, outBuffer, outFence] ( + HStatus hStatus, + HardwareBuffer const& hBuffer, + hidl_handle const& hFence) { + converted = h2b(hStatus, &bStatus) && + h2b(hBuffer, outBuffer) && + h2b(hFence, outFence); + }); + if (!transResult.isOk()) { + LOG(ERROR) << "detachNextBuffer: transaction failed."; + return FAILED_TRANSACTION; + } + if (!converted) { + LOG(ERROR) << "detachNextBuffer: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::attachBuffer( + int* outSlot, sp const& buffer) { + HardwareBuffer hBuffer{}; + uint32_t hGenerationNumber{}; + if (!b2h(buffer, &hBuffer, &hGenerationNumber)) { + LOG(ERROR) << "attachBuffer: invalid input buffer."; + return BAD_VALUE; + } + + bool converted{}; + status_t bStatus{}; + Return transResult = mBase->attachBuffer(hBuffer, hGenerationNumber, + [&converted, &bStatus, outSlot]( + HStatus hStatus, int32_t hSlot, bool releaseAllBuffers) { + converted = h2b(hStatus, &bStatus); + *outSlot = static_cast(hSlot); + if (converted && releaseAllBuffers && bStatus == OK) { + bStatus = IGraphicBufferProducer::RELEASE_ALL_BUFFERS; + } + }); + if (!transResult.isOk()) { + LOG(ERROR) << "attachBuffer: transaction failed."; + return FAILED_TRANSACTION; + } + if (!converted) { + LOG(ERROR) << "attachBuffer: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::queueBuffer( + int slot, + QueueBufferInput const& input, + QueueBufferOutput* output) { + HRect hCrop{}; + (void)b2h(input.crop, &hCrop); + + using HInput = HGraphicBufferProducer::QueueBufferInput; + HInput hInput{ + input.timestamp, + static_cast(input.isAutoTimestamp), + static_cast(input.dataSpace), + {}, // crop + static_cast(input.transform), + static_cast(input.stickyTransform), + {}, // fence + {} // surfaceDamage + }; + + // Convert crop. + if (!b2h(input.crop, &hInput.crop)) { + LOG(ERROR) << "queueBuffer: corrupted input crop rectangle."; + return UNKNOWN_ERROR; + } + + // Convert surfaceDamage. + size_t numRects; + Rect const* rectArray = input.surfaceDamage.getArray(&numRects); + hInput.surfaceDamage.resize(numRects); + for (size_t i = 0; i < numRects; ++i) { + if (!b2h(rectArray[i], &hInput.surfaceDamage[i])) { + LOG(ERROR) << "queueBuffer: corrupted input surface damage."; + return UNKNOWN_ERROR; + } + } + + // Convert fence. + HFenceWrapper hFenceWrapper; + if (!b2h(input.fence, &hFenceWrapper)) { + LOG(ERROR) << "queueBuffer: corrupted input fence."; + return UNKNOWN_ERROR; + } + hInput.fence = hFenceWrapper.getHandle(); + + using HOutput = HGraphicBufferProducer::QueueBufferOutput; + bool converted{}; + status_t bStatus{}; + Return transResult = mBase->queueBuffer( + static_cast(slot), + hInput, + [&converted, &bStatus, output]( + HStatus hStatus, + HOutput const& hOutput) { + converted = h2b(hStatus, &bStatus); + output->width = hOutput.width; + output->height = hOutput.height; + output->transformHint = + static_cast(hOutput.transformHint); + output->numPendingBuffers = hOutput.numPendingBuffers; + output->nextFrameNumber = hOutput.nextFrameNumber; + output->bufferReplaced = hOutput.bufferReplaced; + }); + + if (!transResult.isOk()) { + LOG(ERROR) << "queueBuffer: transaction failed."; + return FAILED_TRANSACTION; + } + if (!converted) { + LOG(ERROR) << "queueBuffer: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::cancelBuffer(int slot, sp const& fence) { + HFenceWrapper hFenceWrapper; + if (!b2h(fence, &hFenceWrapper)) { + LOG(ERROR) << "cancelBuffer: corrupted input fence."; + return UNKNOWN_ERROR; + } + status_t bStatus{}; + Return transResult = mBase->cancelBuffer( + static_cast(slot), + hFenceWrapper.getHandle()); + if (!transResult.isOk()) { + LOG(ERROR) << "cancelBuffer: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "cancelBuffer: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +int H2BGraphicBufferProducer::query(int what, int* value) { + int result{}; + Return transResult = mBase->query( + static_cast(what), + [&result, value](int32_t r, int32_t v) { + result = static_cast(r); + *value = static_cast(v); + }); + if (!transResult.isOk()) { + LOG(ERROR) << "query: transaction failed."; + return FAILED_TRANSACTION; + } + return result; +} + +status_t H2BGraphicBufferProducer::connect( + sp const& listener, int api, + bool producerControlledByApp, QueueBufferOutput* output) { + HConnectionType hConnectionType; + if (!b2h(api, &hConnectionType)) { + LOG(ERROR) << "connect: corrupted input connection type."; + return UNKNOWN_ERROR; + } + sp hListener = nullptr; + if (listener && listener->needsReleaseNotify()) { + hListener = new B2HProducerListener(listener); + if (!hListener) { + LOG(ERROR) << "connect: failed to wrap listener."; + return UNKNOWN_ERROR; + } + } + + using HOutput = HGraphicBufferProducer::QueueBufferOutput; + bool converted{}; + status_t bStatus{}; + Return transResult = mBase->connect( + hListener, + hConnectionType, + producerControlledByApp, + [&converted, &bStatus, output]( + HStatus hStatus, + HOutput hOutput) { + converted = h2b(hStatus, &bStatus); + output->width = hOutput.width; + output->height = hOutput.height; + output->transformHint = + static_cast(hOutput.transformHint); + output->numPendingBuffers = hOutput.numPendingBuffers; + output->nextFrameNumber = hOutput.nextFrameNumber; + output->bufferReplaced = hOutput.bufferReplaced; + }); + if (!transResult.isOk()) { + LOG(ERROR) << "connect: transaction failed."; + return FAILED_TRANSACTION; + } + if (!converted) { + LOG(ERROR) << "connect: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; + +} + +status_t H2BGraphicBufferProducer::disconnect(int api, DisconnectMode mode) { + HConnectionType hConnectionType; + if (mode == DisconnectMode::AllLocal) { + hConnectionType = HConnectionType::CURRENTLY_CONNECTED; + } else if (!b2h(api, &hConnectionType)) { + LOG(ERROR) << "connect: corrupted input connection type."; + return UNKNOWN_ERROR; + } + + status_t bStatus{}; + Return transResult = mBase->disconnect(hConnectionType); + if (!transResult.isOk()) { + LOG(ERROR) << "disconnect: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "disconnect: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::setSidebandStream( + sp const& stream) { + if (stream) { + LOG(INFO) << "setSidebandStream: not supported."; + return INVALID_OPERATION; + } + return OK; +} + +void H2BGraphicBufferProducer::allocateBuffers( + uint32_t width, uint32_t height, + PixelFormat format, uint64_t usage) { + status_t bStatus{}; + Return transResult = mBase->allocateBuffers( + width, height, static_cast(format), usage); + if (!transResult.isOk()) { + LOG(ERROR) << "allocateBuffer: transaction failed."; + return; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "allocateBuffer: corrupted transaction."; + return; + } +} + +status_t H2BGraphicBufferProducer::allowAllocation(bool allow) { + status_t bStatus{}; + Return transResult = mBase->allowAllocation(allow); + if (!transResult.isOk()) { + LOG(ERROR) << "allowAllocation: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "allowAllocation: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::setGenerationNumber( + uint32_t generationNumber) { + status_t bStatus{}; + Return transResult = mBase->setGenerationNumber(generationNumber); + if (!transResult.isOk()) { + LOG(ERROR) << "setGenerationNumber: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "setGenerationNumber: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +String8 H2BGraphicBufferProducer::getConsumerName() const { + String8 bName; + Return transResult = mBase->getConsumerName( + [&bName](hidl_string const& name) { + bName = name.c_str(); + }); + return bName; +} + +status_t H2BGraphicBufferProducer::setSharedBufferMode(bool sharedBufferMode) { + if (sharedBufferMode) { + LOG(INFO) << "setSharedBufferMode: not supported."; + return INVALID_OPERATION; + } + return OK; +} + +status_t H2BGraphicBufferProducer::setAutoRefresh(bool autoRefresh) { + if (autoRefresh) { + LOG(INFO) << "setAutoRefresh: not supported."; + return INVALID_OPERATION; + } + return OK; +} + +status_t H2BGraphicBufferProducer::setDequeueTimeout(nsecs_t timeout) { + status_t bStatus{}; + Return transResult = mBase->setDequeueTimeout( + static_cast(timeout)); + if (!transResult.isOk()) { + LOG(ERROR) << "setDequeueTimeout: transaction failed."; + return FAILED_TRANSACTION; + } + if (!h2b(static_cast(transResult), &bStatus)) { + LOG(ERROR) << "setDequeueTimeout: corrupted transaction."; + return FAILED_TRANSACTION; + } + return bStatus; +} + +status_t H2BGraphicBufferProducer::getLastQueuedBuffer( + sp*, + sp*, + float[16]) { + LOG(INFO) << "getLastQueuedBuffer: not supported."; + return INVALID_OPERATION; +} + +void H2BGraphicBufferProducer::getFrameTimestamps(FrameEventHistoryDelta*) { + LOG(INFO) << "getFrameTimestamps: not supported."; +} + +status_t H2BGraphicBufferProducer::getUniqueId(uint64_t* outId) const { + Return transResult = mBase->getUniqueId(); + if (!transResult.isOk()) { + LOG(ERROR) << "getUniqueId: transaction failed."; + return FAILED_TRANSACTION; + } + *outId = static_cast(transResult); + return OK; +} + +status_t H2BGraphicBufferProducer::getConsumerUsage(uint64_t*) const { + LOG(INFO) << "getConsumerUsage: not supported."; + return INVALID_OPERATION; +} + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/libs/gui/bufferqueue/2.0/H2BProducerListener.cpp b/libs/gui/bufferqueue/2.0/H2BProducerListener.cpp new file mode 100644 index 0000000000..b81a357d63 --- /dev/null +++ b/libs/gui/bufferqueue/2.0/H2BProducerListener.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2019 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "H2BProducerListener@2.0" + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +using ::android::hardware::Return; + +H2BProducerListener::H2BProducerListener(sp const& base) + : CBase{base} { +} + +void H2BProducerListener::onBufferReleased() { + if (mBase) { + Return transResult = mBase->onBuffersReleased(1); + if (!transResult.isOk()) { + LOG(ERROR) << "onBuffersReleased: transaction failed."; + } + } +} + +bool H2BProducerListener::needsReleaseNotify() { + return static_cast(mBase); +} + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + diff --git a/libs/gui/bufferqueue/2.0/types.cpp b/libs/gui/bufferqueue/2.0/types.cpp new file mode 100644 index 0000000000..a11051739f --- /dev/null +++ b/libs/gui/bufferqueue/2.0/types.cpp @@ -0,0 +1,301 @@ +/* + * Copyright 2019 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 +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +// Status +// ====== + +bool b2h(status_t from, HStatus* to, + bool* bufferNeedsReallocation, bool* releaseAllBuffers) { + switch (from) { + case OK: + *to = HStatus::OK; break; + case NO_MEMORY: + *to = HStatus::NO_MEMORY; break; + case NO_INIT: + *to = HStatus::NO_INIT; break; + case BAD_VALUE: + *to = HStatus::BAD_VALUE; break; + case DEAD_OBJECT: + *to = HStatus::DEAD_OBJECT; break; + case INVALID_OPERATION: + *to = HStatus::INVALID_OPERATION; break; + case TIMED_OUT: + *to = HStatus::TIMED_OUT; break; + case WOULD_BLOCK: + *to = HStatus::WOULD_BLOCK; break; + case UNKNOWN_ERROR: + *to = HStatus::UNKNOWN_ERROR; break; + default: + using BGBP = ::android::IGraphicBufferProducer; + status_t mask = + (bufferNeedsReallocation ? BGBP::BUFFER_NEEDS_REALLOCATION : 0) + | (releaseAllBuffers ? BGBP::RELEASE_ALL_BUFFERS : 0); + if (from & ~mask) { + *to = static_cast(from); + } else { + *to = HStatus::OK; + if (bufferNeedsReallocation) { + *bufferNeedsReallocation = from & BGBP::BUFFER_NEEDS_REALLOCATION; + } + if (releaseAllBuffers) { + *releaseAllBuffers = from & BGBP::RELEASE_ALL_BUFFERS; + } + } + } + return true; +} + +bool h2b(HStatus from, status_t* to) { + switch (from) { + case HStatus::OK: + *to = OK; break; + case HStatus::NO_MEMORY: + *to = NO_MEMORY; break; + case HStatus::NO_INIT: + *to = NO_INIT; break; + case HStatus::BAD_VALUE: + *to = BAD_VALUE; break; + case HStatus::DEAD_OBJECT: + *to = DEAD_OBJECT; break; + case HStatus::INVALID_OPERATION: + *to = INVALID_OPERATION; break; + case HStatus::TIMED_OUT: + *to = TIMED_OUT; break; + case HStatus::WOULD_BLOCK: + *to = WOULD_BLOCK; break; + case HStatus::UNKNOWN_ERROR: + *to = UNKNOWN_ERROR; break; + default: + *to = static_cast(from); + } + return true; +} + +// Fence +// ===== + +HFenceWrapper::HFenceWrapper(native_handle_t* h) : mHandle{h} { +} + +HFenceWrapper::~HFenceWrapper() { + native_handle_delete(mHandle); +} + +HFenceWrapper& HFenceWrapper::set(native_handle_t* h) { + native_handle_delete(mHandle); + mHandle = h; + return *this; +} + +HFenceWrapper& HFenceWrapper::operator=(native_handle_t* h) { + return set(h); +} + +hidl_handle HFenceWrapper::getHandle() const { + return hidl_handle{mHandle}; +} + +HFenceWrapper::operator hidl_handle() const { + return getHandle(); +} + +bool b2h(sp const& from, HFenceWrapper* to) { + if (!from) { + to->set(nullptr); + return true; + } + int fenceFd = from->get(); + if (fenceFd == -1) { + to->set(nullptr); + return true; + } + native_handle_t* nh = native_handle_create(1, 0); + if (!nh) { + return false; + } + nh->data[0] = fenceFd; + to->set(nh); + return true; +} + +bool h2b(native_handle_t const* from, sp* to) { + if (!from || from->numFds == 0) { + *to = new ::android::Fence(); + return true; + } + if (from->numFds != 1 || from->numInts != 0) { + return false; + } + *to = new BFence(dup(from->data[0])); + return true; +} + +// ConnectionType +// ============== + +bool b2h(int from, HConnectionType* to) { + *to = static_cast(from); + switch (from) { + case BufferQueueCore::CURRENTLY_CONNECTED_API: + *to = HConnectionType::CURRENTLY_CONNECTED; break; + case NATIVE_WINDOW_API_EGL: + *to = HConnectionType::EGL; break; + case NATIVE_WINDOW_API_CPU: + *to = HConnectionType::CPU; break; + case NATIVE_WINDOW_API_MEDIA: + *to = HConnectionType::MEDIA; break; + case NATIVE_WINDOW_API_CAMERA: + *to = HConnectionType::CAMERA; break; + } + return true; +} + +bool h2b(HConnectionType from, int* to) { + *to = static_cast(from); + switch (from) { + case HConnectionType::CURRENTLY_CONNECTED: + *to = BufferQueueCore::CURRENTLY_CONNECTED_API; break; + case HConnectionType::EGL: + *to = NATIVE_WINDOW_API_EGL; break; + case HConnectionType::CPU: + *to = NATIVE_WINDOW_API_CPU; break; + case HConnectionType::MEDIA: + *to = NATIVE_WINDOW_API_MEDIA; break; + case HConnectionType::CAMERA: + *to = NATIVE_WINDOW_API_CAMERA; break; + } + return true; +} + +// Rect +// ==== + +bool b2h(BRect const& from, HRect* to) { + BRect* dst = reinterpret_cast(to->data()); + dst->left = from.left; + dst->top = from.top; + dst->right = from.right; + dst->bottom = from.bottom; + return true; +} + +bool h2b(HRect const& from, BRect* to) { + BRect const* src = reinterpret_cast(from.data()); + to->left = src->left; + to->top = src->top; + to->right = src->right; + to->bottom = src->bottom; + return true; +} + +// Region +// ====== + +bool b2h(BRegion const& from, HRegion* to) { + size_t numRects; + BRect const* rectArray = from.getArray(&numRects); + to->resize(numRects); + for (size_t i = 0; i < numRects; ++i) { + if (!b2h(rectArray[i], &(*to)[i])) { + return false; + } + } + return true; +} + +bool h2b(HRegion const& from, BRegion* to) { + if (from.size() > 0) { + BRect bRect; + if (!h2b(from[0], &bRect)) { + return false; + } + to->set(bRect); + for (size_t i = 1; i < from.size(); ++i) { + if (!h2b(from[i], &bRect)) { + return false; + } + to->addRectUnchecked( + static_cast(bRect.left), + static_cast(bRect.top), + static_cast(bRect.right), + static_cast(bRect.bottom)); + } + } else { + to->clear(); + } + return true; +} + +// GraphicBuffer +// ============= + +// The handle is not cloned. Its lifetime is tied to the original GraphicBuffer. +bool b2h(sp const& from, HardwareBuffer* to, + uint32_t* toGenerationNumber) { + if (!from) { + return false; + } + AHardwareBuffer* hwBuffer = from->toAHardwareBuffer(); + to->nativeHandle.setTo( + const_cast( + AHardwareBuffer_getNativeHandle(hwBuffer)), + false); + AHardwareBuffer_describe( + hwBuffer, + reinterpret_cast(to->description.data())); + if (toGenerationNumber) { + *toGenerationNumber = from->getGenerationNumber(); + } + return true; +} + +// The handle is cloned. +bool h2b(HardwareBuffer const& from, sp* to) { + AHardwareBuffer_Desc const* desc = + reinterpret_cast( + from.description.data()); + native_handle_t const* handle = from.nativeHandle; + AHardwareBuffer* hwBuffer; + if (AHardwareBuffer_createFromHandle( + desc, handle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, + &hwBuffer) != OK) { + return false; + } + *to = GraphicBuffer::fromAHardwareBuffer(hwBuffer); + return true; +} + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 8ff8d81cf6..2f538adebc 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -35,6 +35,7 @@ #include #include +#include namespace android { // ---------------------------------------------------------------------------- @@ -42,8 +43,6 @@ namespace android { class IProducerListener; class NativeHandle; class Surface; -typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer - HGraphicBufferProducer; /* * This class defines the Binder IPC interface for the producer side of @@ -62,7 +61,16 @@ typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer class IGraphicBufferProducer : public IInterface { public: - DECLARE_HYBRID_META_INTERFACE(GraphicBufferProducer, HGraphicBufferProducer) + using HGraphicBufferProducerV1_0 = + ::android::hardware::graphics::bufferqueue::V1_0:: + IGraphicBufferProducer; + using HGraphicBufferProducerV2_0 = + ::android::hardware::graphics::bufferqueue::V2_0:: + IGraphicBufferProducer; + + DECLARE_HYBRID_META_INTERFACE(GraphicBufferProducer, + HGraphicBufferProducerV1_0, + HGraphicBufferProducerV2_0) enum { // A flag returned by dequeueBuffer when the client needs to call @@ -366,7 +374,6 @@ public: const HdrMetadata& getHdrMetadata() const { return hdrMetadata; } void setHdrMetadata(const HdrMetadata& metadata) { hdrMetadata = metadata; } - private: int64_t timestamp{0}; int isAutoTimestamp{0}; android_dataspace dataSpace{HAL_DATASPACE_UNKNOWN}; diff --git a/libs/gui/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h index e808bd3bc3..a13d8e4945 100644 --- a/libs/gui/include/gui/IProducerListener.h +++ b/libs/gui/include/gui/IProducerListener.h @@ -17,8 +17,10 @@ #ifndef ANDROID_GUI_IPRODUCERLISTENER_H #define ANDROID_GUI_IPRODUCERLISTENER_H +#include +#include #include - +#include #include namespace android { @@ -47,7 +49,14 @@ public: class IProducerListener : public ProducerListener, public IInterface { public: - DECLARE_META_INTERFACE(ProducerListener) + using HProducerListener1 = + ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener; + using HProducerListener2 = + ::android::hardware::graphics::bufferqueue::V2_0::IProducerListener; + DECLARE_HYBRID_META_INTERFACE( + ProducerListener, + HProducerListener1, + HProducerListener2) }; class BnProducerListener : public BnInterface diff --git a/libs/gui/include/gui/bufferqueue/1.0/H2BProducerListener.h b/libs/gui/include/gui/bufferqueue/1.0/H2BProducerListener.h new file mode 100644 index 0000000000..211fdd5351 --- /dev/null +++ b/libs/gui/include/gui/bufferqueue/1.0/H2BProducerListener.h @@ -0,0 +1,52 @@ +/* + * Copyright 2019 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. + */ + +#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_H2BPRODUCERLISTENER_H +#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_H2BPRODUCERLISTENER_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V1_0 { +namespace utils { + +using HProducerListener = ::android::hardware::graphics::bufferqueue::V1_0:: + IProducerListener; + +using BProducerListener = ::android::IProducerListener; + +class H2BProducerListener + : public H2BConverter { +public: + H2BProducerListener(sp const& base); + virtual void onBufferReleased() override; + virtual bool needsReleaseNotify() override; +}; + +} // namespace utils +} // namespace V1_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_H2BPRODUCERLISTENER_H + diff --git a/libs/gui/include/gui/bufferqueue/2.0/B2HGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/2.0/B2HGraphicBufferProducer.h new file mode 100644 index 0000000000..1c58167752 --- /dev/null +++ b/libs/gui/include/gui/bufferqueue/2.0/B2HGraphicBufferProducer.h @@ -0,0 +1,121 @@ +/* + * Copyright 2019 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. + */ + +#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_B2HGRAPHICBUFFERPRODUCER_H +#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_B2HGRAPHICBUFFERPRODUCER_H + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +using HGraphicBufferProducer = + ::android::hardware::graphics::bufferqueue::V2_0:: + IGraphicBufferProducer; +using BGraphicBufferProducer = + ::android:: + IGraphicBufferProducer; +using HProducerListener = + ::android::hardware::graphics::bufferqueue::V2_0:: + IProducerListener; + +using ::android::hardware::Return; +using ::android::hardware::hidl_handle; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; + +using ::android::hardware::graphics::common::V1_2::HardwareBuffer; + +class B2HGraphicBufferProducer : public HGraphicBufferProducer { +public: + B2HGraphicBufferProducer(sp const& base); + + virtual Return setMaxDequeuedBufferCount( + int32_t maxDequeuedBuffers) override; + + virtual Return requestBuffer( + int32_t slot, + requestBuffer_cb _hidl_cb) override; + + virtual Return setAsyncMode(bool async) override; + + virtual Return dequeueBuffer( + DequeueBufferInput const& input, + dequeueBuffer_cb _hidl_cb) override; + + virtual Return detachBuffer(int32_t slot) override; + + virtual Return detachNextBuffer( + detachNextBuffer_cb _hidl_cb) override; + + virtual Return attachBuffer( + HardwareBuffer const& buffer, + uint32_t generationNumber, + attachBuffer_cb _hidl_cb) override; + + virtual Return queueBuffer( + int32_t slot, + QueueBufferInput const& input, + queueBuffer_cb _hidl_cb) override; + + virtual Return cancelBuffer( + int32_t slot, + hidl_handle const& fence) override; + + virtual Return query(int32_t what, query_cb _hidl_cb) override; + + virtual Return connect( + sp const& listener, + HConnectionType api, + bool producerControlledByApp, + connect_cb _hidl_cb) override; + + virtual Return disconnect(HConnectionType api) override; + + virtual Return allocateBuffers( + uint32_t width, uint32_t height, + uint32_t format, uint64_t usage) override; + + virtual Return allowAllocation(bool allow) override; + + virtual Return setGenerationNumber(uint32_t generationNumber) override; + + virtual Return setDequeueTimeout(int64_t timeoutNs) override; + + virtual Return getUniqueId() override; + + virtual Return getConsumerName(getConsumerName_cb _hidl_cb) override; + +protected: + sp mBase; +}; + + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_B2HGRAPHICBUFFERPRODUCER_H diff --git a/libs/gui/include/gui/bufferqueue/2.0/B2HProducerListener.h b/libs/gui/include/gui/bufferqueue/2.0/B2HProducerListener.h new file mode 100644 index 0000000000..b48a4736ad --- /dev/null +++ b/libs/gui/include/gui/bufferqueue/2.0/B2HProducerListener.h @@ -0,0 +1,57 @@ +/* + * Copyright 2019 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. + */ + +#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_B2HPRODUCERLISTENER_H +#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_B2HPRODUCERLISTENER_H + +#include +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +using ::android::hardware::Return; + +using HProducerListener = ::android::hardware::graphics::bufferqueue::V2_0:: + IProducerListener; + +using BProducerListener = ::android::IProducerListener; + +struct B2HProducerListener : public HProducerListener { + explicit B2HProducerListener(sp const& base); + Return onBuffersReleased(uint32_t count) override; +protected: + sp mBase; + bool mNeedsReleaseNotify; +}; + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_B2HPRODUCERLISTENER_H + diff --git a/libs/gui/include/gui/bufferqueue/2.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/2.0/H2BGraphicBufferProducer.h new file mode 100644 index 0000000000..7dd16172cf --- /dev/null +++ b/libs/gui/include/gui/bufferqueue/2.0/H2BGraphicBufferProducer.h @@ -0,0 +1,107 @@ +/* + * Copyright 2019 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. + */ + +#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_H2BGRAPHICBUFFERPRODUCER_H +#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_H2BGRAPHICBUFFERPRODUCER_H + +#include +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +using ::android::BnGraphicBufferProducer; +using ::android::IProducerListener; +using Fence = ::android::Fence; + +using HGraphicBufferProducer = + ::android::hardware::graphics::bufferqueue::V2_0:: + IGraphicBufferProducer; +using HProducerListener = + ::android::hardware::graphics::bufferqueue::V2_0:: + IProducerListener; +using BGraphicBufferProducer = + ::android::IGraphicBufferProducer; + +struct H2BGraphicBufferProducer + : public ::android::H2BConverter { + explicit H2BGraphicBufferProducer( + sp const& base) : CBase(base) {} + + virtual status_t requestBuffer(int slot, sp* buf) override; + virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override; + virtual status_t setAsyncMode(bool async) override; + virtual status_t dequeueBuffer( + int* slot, sp* fence, + uint32_t width, uint32_t height, + PixelFormat format, uint64_t usage, + uint64_t* outBufferAge, + FrameEventHistoryDelta* outTimestamps) override; + virtual status_t detachBuffer(int slot) override; + virtual status_t detachNextBuffer( + sp* outBuffer, + sp* outFence) override; + virtual status_t attachBuffer( + int* outSlot, + sp const& buffer) override; + virtual status_t queueBuffer( + int slot, + QueueBufferInput const& input, + QueueBufferOutput* output) override; + virtual status_t cancelBuffer(int slot, sp const& fence) override; + virtual int query(int what, int* value) override; + virtual status_t connect( + sp const& listener, + int api, + bool producerControlledByApp, + QueueBufferOutput* output) override; + virtual status_t disconnect( + int api, + DisconnectMode mode = DisconnectMode::Api) override; + virtual status_t setSidebandStream(sp const& stream) override; + virtual void allocateBuffers( + uint32_t width, uint32_t height, + PixelFormat format, uint64_t usage) override; + virtual status_t allowAllocation(bool allow) override; + virtual status_t setGenerationNumber(uint32_t generationNumber) override; + virtual String8 getConsumerName() const override; + virtual status_t setSharedBufferMode(bool sharedBufferMode) override; + virtual status_t setAutoRefresh(bool autoRefresh) override; + virtual status_t setDequeueTimeout(nsecs_t timeout) override; + virtual status_t getLastQueuedBuffer(sp* outBuffer, + sp* outFence, float outTransformMatrix[16]) override; + virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override; + virtual status_t getUniqueId(uint64_t* outId) const override; + virtual status_t getConsumerUsage(uint64_t* outUsage) const override; +}; + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_H2BGRAPHICBUFFERPRODUCER_H diff --git a/libs/gui/include/gui/bufferqueue/2.0/H2BProducerListener.h b/libs/gui/include/gui/bufferqueue/2.0/H2BProducerListener.h new file mode 100644 index 0000000000..898920bf8a --- /dev/null +++ b/libs/gui/include/gui/bufferqueue/2.0/H2BProducerListener.h @@ -0,0 +1,52 @@ +/* + * Copyright 2019 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. + */ + +#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_H2BPRODUCERLISTENER_H +#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_H2BPRODUCERLISTENER_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +using HProducerListener = ::android::hardware::graphics::bufferqueue::V2_0:: + IProducerListener; + +using BProducerListener = ::android::IProducerListener; + +class H2BProducerListener + : public H2BConverter { +public: + H2BProducerListener(sp const& base); + virtual void onBufferReleased() override; + virtual bool needsReleaseNotify() override; +}; + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_H2BPRODUCERLISTENER_H + diff --git a/libs/gui/include/gui/bufferqueue/2.0/types.h b/libs/gui/include/gui/bufferqueue/2.0/types.h new file mode 100644 index 0000000000..62176ce2ef --- /dev/null +++ b/libs/gui/include/gui/bufferqueue/2.0/types.h @@ -0,0 +1,129 @@ +/* + * Copyright 2019 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. + */ + +#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_TYPES_H +#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_TYPES_H + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace bufferqueue { +namespace V2_0 { +namespace utils { + +// Status +// ====== + +using HStatus = ::android::hardware::graphics::bufferqueue::V2_0:: + Status; + +// A status_t value may have flags encoded. These flags are decoded into boolean +// values if their corresponding output pointers are not null. +bool b2h(status_t from, HStatus* to, + bool* bufferNeedsReallocation = nullptr, + bool* releaseAllBuffers = nullptr); +// Simple 1-to-1 mapping. If BUFFER_NEEDS_REALLOCATION or RELEASE_ALL_BUFFERS +// needs to be added, it must be done manually afterwards. +bool h2b(HStatus from, status_t* to); + +// Fence +// ===== + +using BFence = ::android::Fence; +// This class manages the lifetime of a copied handle. Its destructor calls +// native_handle_delete() but not native_handle_close(). +struct HFenceWrapper { + HFenceWrapper() = default; + // Sets mHandle to a new value. + HFenceWrapper(native_handle_t* h); + // Deletes mHandle without closing. + ~HFenceWrapper(); + // Deletes mHandle without closing, then sets mHandle to a new value. + HFenceWrapper& set(native_handle_t* h); + HFenceWrapper& operator=(native_handle_t* h); + // Returns a non-owning hidl_handle pointing to mHandle. + hidl_handle getHandle() const; + operator hidl_handle() const; +protected: + native_handle_t* mHandle{nullptr}; +}; + +// Does not clone the fd---only copy the fd. The returned HFenceWrapper should +// not outlive the input Fence object. +bool b2h(sp const& from, HFenceWrapper* to); +// Clones the fd and puts it in a new Fence object. +bool h2b(native_handle_t const* from, sp* to); + +// ConnectionType +// ============== + +using HConnectionType = ::android::hardware::graphics::bufferqueue::V2_0:: + ConnectionType; + +bool b2h(int from, HConnectionType* to); +bool h2b(HConnectionType from, int* to); + +// Rect +// ==== + +using BRect = ::android::Rect; +using HRect = ::android::hardware::graphics::common::V1_2::Rect; + +bool b2h(BRect const& from, HRect* to); +bool h2b(HRect const& from, BRect* to); + +// Region +// ====== + +using BRegion = ::android::Region; +using HRegion = ::android::hardware::hidl_vec; + +bool b2h(BRegion const& from, HRegion* to); +bool h2b(HRegion const& from, BRegion* to); + +// GraphicBuffer +// ============= + +using HardwareBuffer = ::android::hardware::graphics::common::V1_2:: + HardwareBuffer; +using HardwareBufferDescription = ::android::hardware::graphics::common::V1_2:: + HardwareBufferDescription; + +// Does not clone the handle. The returned HardwareBuffer should not outlive the +// input GraphicBuffer. Note that HardwareBuffer does not carry the generation +// number, so this function needs another output argument. +bool b2h(sp const& from, HardwareBuffer* to, + uint32_t* toGenerationNumber = nullptr); +// Clones the handle and creates a new GraphicBuffer from the cloned handle. +// Note that the generation number of the GraphicBuffer has to be set manually +// afterwards because HardwareBuffer does not have such information. +bool h2b(HardwareBuffer const& from, sp* to); + +} // namespace utils +} // namespace V2_0 +} // namespace bufferqueue +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V2_0_TYPES_H + diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp index 994e953e76..52fc9d5bad 100644 --- a/libs/nativewindow/AHardwareBuffer.cpp +++ b/libs/nativewindow/AHardwareBuffer.cpp @@ -636,11 +636,11 @@ uint64_t AHardwareBuffer_convertFromGrallocUsageBits(uint64_t usage) { } const GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(const AHardwareBuffer* buffer) { - return reinterpret_cast(buffer); + return GraphicBuffer::fromAHardwareBuffer(buffer); } GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(AHardwareBuffer* buffer) { - return reinterpret_cast(buffer); + return GraphicBuffer::fromAHardwareBuffer(buffer); } const ANativeWindowBuffer* AHardwareBuffer_to_ANativeWindowBuffer(const AHardwareBuffer* buffer) { @@ -652,7 +652,7 @@ ANativeWindowBuffer* AHardwareBuffer_to_ANativeWindowBuffer(AHardwareBuffer* buf } AHardwareBuffer* AHardwareBuffer_from_GraphicBuffer(GraphicBuffer* buffer) { - return reinterpret_cast(buffer); + return buffer->toAHardwareBuffer(); } } // namespace android diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp index d8478848cb..27ab482676 100644 --- a/libs/nativewindow/Android.bp +++ b/libs/nativewindow/Android.bp @@ -24,7 +24,7 @@ ndk_headers { cc_library_headers { name: "libnativewindow_headers", export_include_dirs: ["include"], - vendor_available: false, + vendor_available: true, } ndk_library { diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 4ca1781be1..e521b613a0 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -124,7 +124,6 @@ cc_library_shared { exclude_header_libs: [ "libbufferhub_headers", "libdvr_headers", - "libnativewindow_headers", ], exclude_shared_libs: [ "android.frameworks.bufferhub@1.0", @@ -152,6 +151,7 @@ cc_library_shared { export_header_lib_headers: [ "libbase_headers", "libnativebase_headers", + "libnativewindow_headers", "libhardware_headers", "libui_headers", ], diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 79958ece9e..f800627ef7 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -49,6 +49,22 @@ sp GraphicBuffer::from(ANativeWindowBuffer* anwb) { return static_cast(anwb); } +GraphicBuffer* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer* buffer) { + return reinterpret_cast(buffer); +} + +GraphicBuffer const* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer const* buffer) { + return reinterpret_cast(buffer); +} + +AHardwareBuffer* GraphicBuffer::toAHardwareBuffer() { + return reinterpret_cast(this); +} + +AHardwareBuffer const* GraphicBuffer::toAHardwareBuffer() const { + return reinterpret_cast(this); +} + GraphicBuffer::GraphicBuffer() : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) diff --git a/libs/ui/include/ui/Fence.h b/libs/ui/include/ui/Fence.h index ec67fa972c..6efecd3c0e 100644 --- a/libs/ui/include/ui/Fence.h +++ b/libs/ui/include/ui/Fence.h @@ -99,6 +99,12 @@ public: // be returned and errno will indicate the problem. int dup() const; + // Return the underlying file descriptor without giving up ownership. The + // returned file descriptor is only valid for as long as the owning Fence + // object lives. (If the situation is unclear, dup() is always a safer + // option.) + int get() const { return mFenceFd.get(); } + // getSignalTime returns the system monotonic clock time at which the // fence transitioned to the signaled state. If the fence is not signaled // then SIGNAL_TIME_PENDING is returned. If the fence is invalid or if an diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 4d4ee68194..e0c655813d 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -78,6 +79,10 @@ public: static sp from(ANativeWindowBuffer *); + static GraphicBuffer* fromAHardwareBuffer(AHardwareBuffer*); + static GraphicBuffer const* fromAHardwareBuffer(AHardwareBuffer const*); + AHardwareBuffer* toAHardwareBuffer(); + AHardwareBuffer const* toAHardwareBuffer() const; // Create a GraphicBuffer to be unflatten'ed into or be reallocated. GraphicBuffer(); -- cgit v1.2.3-59-g8ed1b From 7791e64f9f74d61ef60c281e614f617a045e01b2 Mon Sep 17 00:00:00 2001 From: Tianyu Jiang Date: Fri, 15 Feb 2019 18:26:17 -0800 Subject: Support GraphicBuffer::flatten and GraphicBuffer::unflatten with BufferHub flatten() calls duplicate on BufferHubBuffer object and flattens the token obtained from duplicate(). unflatten() reconstruct the token, import a BufferHubBuffer object and reinitialize the GraphicBuffer object using the imported BufferHubBuffer. Bug: 73550905 Test: GraphicBuffer_test Test: cts-tradefed run singleCommand cts -m CtsNativeHardwareTestCases \ --skip-preconditions --skip-device-info Change-Id: I511dde8902893e593829b81e4d838dc3561fb009 --- libs/ui/GraphicBuffer.cpp | 116 +++++++++++++++++++++++++++++++---- libs/ui/include/ui/GraphicBuffer.h | 12 ++++ libs/ui/tests/GraphicBuffer_test.cpp | 45 ++++++++++++++ 3 files changed, 161 insertions(+), 12 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 79958ece9e..ca9f3ee131 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -355,14 +355,29 @@ status_t GraphicBuffer::isSupported(uint32_t inWidth, uint32_t inHeight, PixelFo } size_t GraphicBuffer::getFlattenedSize() const { +#ifndef LIBUI_IN_VNDK + if (mBufferHubBuffer != nullptr) { + return 48; + } +#endif return static_cast(13 + (handle ? mTransportNumInts : 0)) * sizeof(int); } size_t GraphicBuffer::getFdCount() const { +#ifndef LIBUI_IN_VNDK + if (mBufferHubBuffer != nullptr) { + return 0; + } +#endif return static_cast(handle ? mTransportNumFds : 0); } status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { +#ifndef LIBUI_IN_VNDK + if (mBufferHubBuffer != nullptr) { + return flattenBufferHubBuffer(buffer, size, fds, count); + } +#endif size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); if (size < sizeNeeded) return NO_MEMORY; @@ -389,7 +404,7 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& buf[11] = int32_t(mTransportNumInts); memcpy(fds, handle->data, static_cast(mTransportNumFds) * sizeof(int)); memcpy(buf + 13, handle->data + handle->numFds, - static_cast(mTransportNumInts) * sizeof(int)); + static_cast(mTransportNumInts) * sizeof(int)); } buffer = static_cast(static_cast(buffer) + sizeNeeded); @@ -398,17 +413,11 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& fds += mTransportNumFds; count -= static_cast(mTransportNumFds); } - return NO_ERROR; } -status_t GraphicBuffer::unflatten( - void const*& buffer, size_t& size, int const*& fds, size_t& count) { - if (size < 12 * sizeof(int)) { - android_errorWriteLog(0x534e4554, "114223584"); - return NO_MEMORY; - } - +status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& fds, + size_t& count) { int const* buf = static_cast(buffer); // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!! @@ -420,10 +429,21 @@ status_t GraphicBuffer::unflatten( } else if (buf[0] == 'GBFR') { // old version, when usage bits were 32-bits flattenWordCount = 12; + } else if (buf[0] == 'BHBB') { // BufferHub backed buffer. +#ifndef LIBUI_IN_VNDK + return unflattenBufferHubBuffer(buffer, size, fds, count); +#else + return BAD_TYPE; +#endif } else { return BAD_TYPE; } + if (size < 12 * sizeof(int)) { + android_errorWriteLog(0x534e4554, "114223584"); + return NO_MEMORY; + } + const size_t numFds = static_cast(buf[10]); const size_t numInts = static_cast(buf[11]); @@ -464,8 +484,8 @@ status_t GraphicBuffer::unflatten( } else { usage = uint64_t(usage_deprecated); } - native_handle* h = native_handle_create( - static_cast(numFds), static_cast(numInts)); + native_handle* h = + native_handle_create(static_cast(numFds), static_cast(numInts)); if (!h) { width = height = stride = format = usage_deprecated = 0; layerCount = 0; @@ -514,11 +534,83 @@ status_t GraphicBuffer::unflatten( size -= sizeNeeded; fds += numFds; count -= numFds; - return NO_ERROR; } #ifndef LIBUI_IN_VNDK +status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, + size_t& count) const { + sp tokenHandle = mBufferHubBuffer->duplicate(); + if (tokenHandle == nullptr || tokenHandle->handle() == nullptr || + tokenHandle->handle()->numFds != 0) { + return BAD_VALUE; + } + + // Size needed for one label, one number of ints inside the token, one generation number and + // the token itself. + int numIntsInToken = tokenHandle->handle()->numInts; + const size_t sizeNeeded = static_cast(3 + numIntsInToken) * sizeof(int); + if (size < sizeNeeded) { + ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__, + static_cast(sizeNeeded), static_cast(size)); + return NO_MEMORY; + } + size -= sizeNeeded; + + int* buf = static_cast(buffer); + buf[0] = 'BHBB'; + buf[1] = numIntsInToken; + memcpy(buf + 2, tokenHandle->handle()->data, static_cast(numIntsInToken) * sizeof(int)); + buf[2 + numIntsInToken] = static_cast(mGenerationNumber); + + // Do not pass fds if it is BufferHubBuffer backed GraphicBuffer. Not modifying fds or count. + fds += 0; + count -= 0; + return NO_ERROR; +} + +status_t GraphicBuffer::unflattenBufferHubBuffer(void const*& buffer, size_t& size, int const*& fds, + size_t& count) { + const int* buf = static_cast(buffer); + int numIntsInToken = buf[1]; + // Size needed for one label, one number of ints inside the token, one generation number and + // the token itself. + const size_t sizeNeeded = static_cast(3 + numIntsInToken) * sizeof(int); + if (size < sizeNeeded) { + ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__, + static_cast(sizeNeeded), static_cast(size)); + return NO_MEMORY; + } + size -= sizeNeeded; + native_handle_t* importToken = native_handle_create(/*numFds=*/0, /*numInts=*/numIntsInToken); + memcpy(importToken->data, buf + 2, static_cast(buf[1]) * sizeof(int)); + sp importTokenHandle = NativeHandle::create(importToken, /*ownHandle=*/true); + std::unique_ptr bufferHubBuffer = BufferHubBuffer::import(importTokenHandle); + if (bufferHubBuffer == nullptr || bufferHubBuffer.get() == nullptr) { + return BAD_VALUE; + } + // Reconstruct this GraphicBuffer object using the new BufferHubBuffer object. + if (handle) { + free_handle(); + } + mId = 0; + mGenerationNumber = static_cast(buf[2 + numIntsInToken]); + mInitCheck = + initWithHandle(bufferHubBuffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE, + bufferHubBuffer->desc().width, bufferHubBuffer->desc().height, + static_cast(bufferHubBuffer->desc().format), + bufferHubBuffer->desc().layers, bufferHubBuffer->desc().usage, + bufferHubBuffer->desc().stride); + mBufferId = bufferHubBuffer->id(); + mBufferHubBuffer.reset(std::move(bufferHubBuffer.get())); + + // BufferHubBuffer backed GraphicBuffer does not have flattened handle. Not modifying fds or + // count. + fds += 0; + count -= 0; + return NO_ERROR; +} + bool GraphicBuffer::isBufferHubBuffer() const { return mBufferHubBuffer != nullptr; } diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 4d4ee68194..23337a4eea 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -271,6 +271,18 @@ private: uint32_t mGenerationNumber; #ifndef LIBUI_IN_VNDK + // Flatten this GraphicBuffer object if backed by BufferHubBuffer. + status_t flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, size_t& count) const; + + // Unflatten into BufferHubBuffer backed GraphicBuffer. + // Unflatten will fail if the original GraphicBuffer object is destructed. For instance, a + // GraphicBuffer backed by BufferHubBuffer_1 flatten in process/thread A, transport the token + // to process/thread B through a socket, BufferHubBuffer_1 dies and bufferhub invalidated the + // token. Race condition occurs between the invalidation of the token in bufferhub process and + // process/thread B trying to unflatten and import the buffer with that token. + status_t unflattenBufferHubBuffer(void const*& buffer, size_t& size, int const*& fds, + size_t& count); + // Stores a BufferHubBuffer that handles buffer signaling, identification. std::unique_ptr mBufferHubBuffer; #endif // LIBUI_IN_VNDK diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp index c767ce02fc..a7c248c105 100644 --- a/libs/ui/tests/GraphicBuffer_test.cpp +++ b/libs/ui/tests/GraphicBuffer_test.cpp @@ -74,4 +74,49 @@ TEST_F(GraphicBufferTest, BufferIdMatchesBufferHubBufferId) { EXPECT_EQ(gb->getBufferId(), b1_id); } +TEST_F(GraphicBufferTest, flattenAndUnflatten) { + std::unique_ptr b1 = + BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, + kTestUsage, /*userMetadataSize=*/0); + ASSERT_NE(b1, nullptr); + sp gb1(new GraphicBuffer(std::move(b1))); + gb1->setGenerationNumber(42); + + size_t flattenedSize = gb1->getFlattenedSize(); + EXPECT_EQ(flattenedSize, 48); + size_t fdCount = gb1->getFdCount(); + EXPECT_EQ(fdCount, 0); + + int data[flattenedSize]; + int fds[0]; + + // Make copies of needed items since flatten modifies them. + size_t flattenedSizeCopy = flattenedSize; + size_t fdCountCopy = fdCount; + void* dataStart = data; + int* fdsStart = fds; + status_t err = gb1->flatten(dataStart, flattenedSizeCopy, fdsStart, fdCountCopy); + ASSERT_EQ(err, NO_ERROR); + EXPECT_EQ(flattenedSizeCopy, 0); + EXPECT_EQ(fdCountCopy, 0); + + size_t unflattenSize = flattenedSize; + size_t unflattenFdCount = fdCount; + const void* unflattenData = static_cast(dataStart); + const int* unflattenFdData = static_cast(fdsStart); + + GraphicBuffer* gb2 = new GraphicBuffer(); + err = gb2->unflatten(unflattenData, unflattenSize, unflattenFdData, unflattenFdCount); + ASSERT_EQ(err, NO_ERROR); + EXPECT_TRUE(gb2->isBufferHubBuffer()); + + EXPECT_EQ(gb2->getWidth(), kTestWidth); + EXPECT_EQ(gb2->getHeight(), kTestHeight); + EXPECT_EQ(static_cast(gb2->getPixelFormat()), kTestFormat); + EXPECT_EQ(gb2->getUsage(), kTestUsage); + EXPECT_EQ(gb2->getLayerCount(), kTestLayerCount); + EXPECT_EQ(gb1->getBufferId(), gb2->getBufferId()); + EXPECT_EQ(gb2->getGenerationNumber(), 42); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From 78b7220f542826771223f9b5c0b876874dd398d2 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 15 Mar 2019 14:58:34 -0700 Subject: blast: drop buffer from SF's cache when destroyed When an app drops its reference to an AHardwareBuffer, the buffer should be removed from the client and SurfaceFlinger caches. Ideally, both caches would have wp to the buffer and the buffer would automatically be removed from the cache. Unfortunately, GraphicBuffers are refcounted per process. If SurfaceFlinger just has a wp to the GraphicBuffer, the buffer's destructor will be called and SurfaceFlinger will lose access to the buffer. SurfaceFlinger can't just hold onto a sp to the buffer because then the buffer wouldn't be destoryed when the app drops its reference. Instead, when the app process drops its last strong reference, GraphicBuffer will send a callback to the client side cache. The cache will send a Transaction to SurfaceFlinger to drop its sp to the buffer. Bug: 127689853 Test: SurfaceFlinger_test Change-Id: I2182578ed33d7c731945cb88cd1decb2892266b0 --- libs/gui/ISurfaceComposer.cpp | 12 +- libs/gui/LayerState.cpp | 4 +- libs/gui/SurfaceComposerClient.cpp | 162 ++++++++++++---------- libs/gui/include/gui/ISurfaceComposer.h | 4 +- libs/gui/include/gui/LayerState.h | 9 +- libs/gui/include/gui/SurfaceComposerClient.h | 10 ++ libs/gui/tests/Surface_test.cpp | 3 +- libs/ui/GraphicBuffer.cpp | 7 + libs/ui/include/ui/GraphicBuffer.h | 20 +++ services/surfaceflinger/BufferStateLayerCache.cpp | 39 ++++-- services/surfaceflinger/BufferStateLayerCache.h | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 49 ++++--- services/surfaceflinger/SurfaceFlinger.h | 11 +- 13 files changed, 218 insertions(+), 120 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 247dc8d9d2..bc63d315e0 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -68,7 +68,8 @@ public: const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& commands, - int64_t desiredPresentTime) { + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -86,6 +87,8 @@ public: data.writeStrongBinder(applyToken); commands.write(data); data.writeInt64(desiredPresentTime); + data.writeStrongBinder(uncacheBuffer.token); + data.writeUint64(uncacheBuffer.cacheId); remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -970,8 +973,13 @@ status_t BnSurfaceComposer::onTransact( inputWindowCommands.read(data); int64_t desiredPresentTime = data.readInt64(); + + cached_buffer_t uncachedBuffer; + uncachedBuffer.token = data.readStrongBinder(); + uncachedBuffer.cacheId = data.readUint64(); + setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands, - desiredPresentTime); + desiredPresentTime, uncachedBuffer); return NO_ERROR; } case BOOT_FINISHED: { diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 84ba64494f..f6ca9e8f0b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -95,7 +95,7 @@ status_t layer_state_t::write(Parcel& output) const } output.writeStrongBinder(cachedBuffer.token); - output.writeInt32(cachedBuffer.bufferId); + output.writeUint64(cachedBuffer.cacheId); output.writeParcelable(metadata); output.writeFloat(bgColorAlpha); @@ -173,7 +173,7 @@ status_t layer_state_t::read(const Parcel& input) } cachedBuffer.token = input.readStrongBinder(); - cachedBuffer.bufferId = input.readInt32(); + cachedBuffer.cacheId = input.readUint64(); input.readParcelable(&metadata); bgColorAlpha = input.readFloat(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b0e827536d..39cd62fa10 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -233,6 +233,8 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener // --------------------------------------------------------------------------- +void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId); + class BufferCache : public Singleton { public: BufferCache() : token(new BBinder()) {} @@ -241,77 +243,57 @@ public: return IInterface::asBinder(TransactionCompletedListener::getIInstance()); } - int32_t getId(const sp& buffer) { + status_t getCacheId(const sp& buffer, uint64_t* cacheId) { std::lock_guard lock(mMutex); - auto itr = mBuffers.find(buffer); + auto itr = mBuffers.find(buffer->getId()); if (itr == mBuffers.end()) { - return -1; + return BAD_VALUE; } - itr->second.counter = getCounter(); - return itr->second.id; + itr->second = getCounter(); + *cacheId = buffer->getId(); + return NO_ERROR; } - int32_t cache(const sp& buffer) { + uint64_t cache(const sp& buffer) { std::lock_guard lock(mMutex); - int32_t bufferId = getNextAvailableId(); + if (mBuffers.size() >= BUFFER_CACHE_MAX_SIZE) { + evictLeastRecentlyUsedBuffer(); + } + + buffer->addDeathCallback(bufferCacheCallback, nullptr); - mBuffers[buffer].id = bufferId; - mBuffers[buffer].counter = getCounter(); - return bufferId; + mBuffers[buffer->getId()] = getCounter(); + return buffer->getId(); } -private: - int32_t evictDestroyedBuffer() REQUIRES(mMutex) { - auto itr = mBuffers.begin(); - while (itr != mBuffers.end()) { - auto& buffer = itr->first; - if (buffer == nullptr || buffer.promote() == nullptr) { - int32_t bufferId = itr->second.id; - mBuffers.erase(itr); - return bufferId; - } - itr++; - } - return -1; + void uncache(uint64_t cacheId) { + std::lock_guard lock(mMutex); + uncacheLocked(cacheId); } - int32_t evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) { - if (mBuffers.size() < 0) { - return -1; - } + void uncacheLocked(uint64_t cacheId) REQUIRES(mMutex) { + mBuffers.erase(cacheId); + SurfaceComposerClient::doUncacheBufferTransaction(cacheId); + } + +private: + void evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) { auto itr = mBuffers.begin(); - uint64_t minCounter = itr->second.counter; + uint64_t minCounter = itr->second; auto minBuffer = itr; itr++; while (itr != mBuffers.end()) { - uint64_t counter = itr->second.counter; + uint64_t counter = itr->second; if (counter < minCounter) { minCounter = counter; minBuffer = itr; } itr++; } - int32_t minBufferId = minBuffer->second.id; - mBuffers.erase(minBuffer); - return minBufferId; - } - - int32_t getNextAvailableId() REQUIRES(mMutex) { - static int32_t id = 0; - if (id + 1 < BUFFER_CACHE_MAX_SIZE) { - return id++; - } - - // There are no more valid cache ids. To set additional buffers, evict existing buffers - // and reuse their cache ids. - int32_t bufferId = evictDestroyedBuffer(); - if (bufferId > 0) { - return bufferId; - } - return evictLeastRecentlyUsedBuffer(); + uncacheLocked(minBuffer->first); } uint64_t getCounter() REQUIRES(mMutex) { @@ -319,18 +301,8 @@ private: return counter++; } - struct Metadata { - // The cache id of a buffer that can be set to ISurfaceComposer. When ISurfaceComposer - // recieves this id, it can retrieve the buffer from its cache. Caching GraphicBuffers - // is important because sending them across processes is expensive. - int32_t id = 0; - // When a buffer is set, a counter is incremented and stored in the cache's metadata. - // When an buffer must be evicted, the entry with the lowest counter value is chosen. - uint64_t counter = 0; - }; - std::mutex mMutex; - std::map, Metadata> mBuffers GUARDED_BY(mMutex); + std::map mBuffers GUARDED_BY(mMutex); // Used by ISurfaceComposer to identify which process is sending the cached buffer. sp token; @@ -338,6 +310,11 @@ private: ANDROID_SINGLETON_STATIC_INSTANCE(BufferCache); +void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId) { + // GraphicBuffer id's are used as the cache ids. + BufferCache::getInstance().uncache(graphicBufferId); +} + // --------------------------------------------------------------------------- SurfaceComposerClient::Transaction::Transaction(const Transaction& other) @@ -385,6 +362,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mInputWindowCommands.merge(other.mInputWindowCommands); other.mInputWindowCommands.clear(); + mContainsBuffer = other.mContainsBuffer; + other.mContainsBuffer = false; + return *this; } @@ -401,7 +381,50 @@ void SurfaceComposerClient::doDropReferenceTransaction(const sp& handle s.state.parentHandleForChild = nullptr; composerStates.add(s); - sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1); + sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1, {}); +} + +void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { + sp sf(ComposerService::getComposerService()); + + cached_buffer_t uncacheBuffer; + uncacheBuffer.token = BufferCache::getInstance().getToken(); + uncacheBuffer.cacheId = cacheId; + + sf->setTransactionState({}, {}, 0, nullptr, {}, -1, uncacheBuffer); +} + +void SurfaceComposerClient::Transaction::cacheBuffers() { + if (!mContainsBuffer) { + return; + } + + size_t count = 0; + for (auto& [sc, cs] : mComposerStates) { + layer_state_t* s = getLayerState(sc); + if (!(s->what & layer_state_t::eBufferChanged)) { + continue; + } + + uint64_t cacheId = 0; + status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId); + if (ret == NO_ERROR) { + s->what &= ~static_cast(layer_state_t::eBufferChanged); + s->buffer = nullptr; + } else { + cacheId = BufferCache::getInstance().cache(s->buffer); + } + s->what |= layer_state_t::eCachedBufferChanged; + s->cachedBuffer.token = BufferCache::getInstance().getToken(); + s->cachedBuffer.cacheId = cacheId; + + // If we have more buffers than the size of the cache, we should stop caching so we don't + // evict other buffers in this transaction + count++; + if (count >= BUFFER_CACHE_MAX_SIZE) { + break; + } + } } status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { @@ -437,6 +460,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { } mListenerCallbacks.clear(); + cacheBuffers(); + Vector composerStates; Vector displayStates; uint32_t flags = 0; @@ -468,7 +493,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands, - mDesiredPresentTime); + mDesiredPresentTime, + {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/); mInputWindowCommands.clear(); mStatus = NO_ERROR; return NO_ERROR; @@ -882,20 +908,12 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe mStatus = BAD_INDEX; return *this; } - - int32_t bufferId = BufferCache::getInstance().getId(buffer); - if (bufferId < 0) { - bufferId = BufferCache::getInstance().cache(buffer); - - s->what |= layer_state_t::eBufferChanged; - s->buffer = buffer; - } - - s->what |= layer_state_t::eCachedBufferChanged; - s->cachedBuffer.token = BufferCache::getInstance().getToken(); - s->cachedBuffer.bufferId = bufferId; + s->what |= layer_state_t::eBufferChanged; + s->buffer = buffer; registerSurfaceControlForCallback(sc); + + mContainsBuffer = true; return *this; } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 8f54fee22f..0ef5b39641 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -40,6 +40,7 @@ namespace android { // ---------------------------------------------------------------------------- +struct cached_buffer_t; struct ComposerState; struct DisplayState; struct DisplayInfo; @@ -131,7 +132,8 @@ public: const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime) = 0; + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) = 0; /* signal that we're done booting. * Requires ACCESS_SURFACE_FLINGER permission diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 35e795c30b..77bf8f1dc5 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -41,6 +41,11 @@ namespace android { class Parcel; class ISurfaceComposerClient; +struct cached_buffer_t { + sp token = nullptr; + uint64_t cacheId; +}; + /* * Used to communicate layer information between SurfaceFlinger and its clients. */ @@ -133,10 +138,6 @@ struct layer_state_t { float dtdy{0}; float dsdy{0}; }; - struct cached_buffer_t { - sp token = nullptr; - int32_t bufferId = -1; - }; sp surface; uint64_t what; float x; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 39d6d13682..593a5e7d81 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -165,6 +165,12 @@ public: static void doDropReferenceTransaction(const sp& handle, const sp& client); + /** + * Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is + * in order with other transactions that use buffers. + */ + static void doUncacheBufferTransaction(uint64_t cacheId); + // Queries whether a given display is wide color display. static status_t isWideColorDisplay(const sp& display, bool* outIsWideColorDisplay); @@ -279,6 +285,9 @@ public: bool mAnimation = false; bool mEarlyWakeup = false; + // Indicates that the Transaction contains a buffer that should be cached + bool mContainsBuffer = false; + // mDesiredPresentTime is the time in nanoseconds that the client would like the transaction // to be presented. When it is not possible to present at exactly that time, it will be // presented after the time has passed. @@ -297,6 +306,7 @@ public: layer_state_t* getLayerState(const sp& sc); DisplayState& getDisplayState(const sp& token); + void cacheBuffers(); void registerSurfaceControlForCallback(const sp& sc); public: diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 06fe86c0cf..94b669dde4 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -560,7 +560,8 @@ public: const Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, const InputWindowCommands& /*inputWindowCommands*/, - int64_t /*desiredPresentTime*/) override {} + int64_t /*desiredPresentTime*/, + const cached_buffer_t& /*cachedBuffer*/) override {} void bootFinished() override {} bool authenticateSurfaceTexture( diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index f800627ef7..637a9cf725 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -133,6 +133,9 @@ GraphicBuffer::~GraphicBuffer() if (handle) { free_handle(); } + for (auto& [callback, context] : mDeathCallbacks) { + callback(context, mId); + } } void GraphicBuffer::free_handle() @@ -534,6 +537,10 @@ status_t GraphicBuffer::unflatten( return NO_ERROR; } +void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context) { + mDeathCallbacks.emplace_back(deathCallback, context); +} + #ifndef LIBUI_IN_VNDK bool GraphicBuffer::isBufferHubBuffer() const { return mBufferHubBuffer != nullptr; diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 1c88777961..f86ca59b52 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -42,6 +44,8 @@ class BufferHubBuffer; class GraphicBufferMapper; +using GraphicBufferDeathCallback = std::function; + // =========================================================================== // GraphicBuffer // =========================================================================== @@ -219,6 +223,8 @@ public: return mBufferMapper.getMapperVersion(); } + void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context); + #ifndef LIBUI_IN_VNDK // Returns whether this GraphicBuffer is backed by BufferHubBuffer. bool isBufferHubBuffer() const; @@ -280,6 +286,20 @@ private: // IGBP::setGenerationNumber), attempts to attach the buffer will fail. uint32_t mGenerationNumber; + // Send a callback when a GraphicBuffer dies. + // + // This is used for BufferStateLayer caching. GraphicBuffers are refcounted per process. When + // A GraphicBuffer doesn't have any more sp<> in a process, it is destroyed. This causes + // problems when trying to implicitcly cache across process boundaries. Ideally, both sides + // of the cache would hold onto wp<> references. When an app dropped its sp<>, the GraphicBuffer + // would be destroyed. Unfortunately, when SurfaceFlinger has only a wp<> reference to the + // GraphicBuffer, it immediately goes out of scope in the SurfaceFlinger process. SurfaceFlinger + // must hold onto a sp<> to the buffer. When the GraphicBuffer goes out of scope in the app's + // process, the client side cache will get this callback. It erases the buffer from its cache + // and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer. + std::vector> + mDeathCallbacks; + #ifndef LIBUI_IN_VNDK // Stores a BufferHubBuffer that handles buffer signaling, identification. std::unique_ptr mBufferHubBuffer; diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp index cb02d16007..51ca45c53a 100644 --- a/services/surfaceflinger/BufferStateLayerCache.cpp +++ b/services/surfaceflinger/BufferStateLayerCache.cpp @@ -23,21 +23,14 @@ #include "BufferStateLayerCache.h" -#define VALID_CACHE_ID(id) ((id) >= 0 || (id) < (BUFFER_CACHE_MAX_SIZE)) - namespace android { ANDROID_SINGLETON_STATIC_INSTANCE(BufferStateLayerCache); BufferStateLayerCache::BufferStateLayerCache() : mDeathRecipient(new CacheDeathRecipient) {} -void BufferStateLayerCache::add(sp processToken, int32_t id, +void BufferStateLayerCache::add(const sp& processToken, uint64_t id, const sp& buffer) { - if (!VALID_CACHE_ID(id)) { - ALOGE("failed to cache buffer: invalid buffer id"); - return; - } - if (!processToken) { ALOGE("failed to cache buffer: invalid process token"); return; @@ -61,15 +54,33 @@ void BufferStateLayerCache::add(sp processToken, int32_t id, } auto& processBuffers = mBuffers[processToken]; + + if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) { + ALOGE("failed to cache buffer: cache is full"); + return; + } + processBuffers[id] = buffer; } -sp BufferStateLayerCache::get(sp processToken, int32_t id) { - if (!VALID_CACHE_ID(id)) { - ALOGE("failed to get buffer: invalid buffer id"); - return nullptr; +void BufferStateLayerCache::erase(const sp& processToken, uint64_t id) { + if (!processToken) { + ALOGE("failed to uncache buffer: invalid process token"); + return; + } + + std::lock_guard lock(mMutex); + + if (mBuffers.find(processToken) == mBuffers.end()) { + ALOGE("failed to uncache buffer: process token not found"); + return; } + auto& processBuffers = mBuffers[processToken]; + processBuffers.erase(id); +} + +sp BufferStateLayerCache::get(const sp& processToken, uint64_t id) { if (!processToken) { ALOGE("failed to cache buffer: invalid process token"); return nullptr; @@ -82,8 +93,8 @@ sp BufferStateLayerCache::get(sp processToken, int32_t i return nullptr; } - if (id >= itr->second.size()) { - ALOGE("failed to get buffer: id outside the bounds of the cache"); + if (itr->second.find(id) == itr->second.end()) { + ALOGE("failed to get buffer: buffer not found"); return nullptr; } diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h index ede3feb1c8..415c09cf96 100644 --- a/services/surfaceflinger/BufferStateLayerCache.h +++ b/services/surfaceflinger/BufferStateLayerCache.h @@ -34,14 +34,16 @@ class BufferStateLayerCache : public Singleton { public: BufferStateLayerCache(); - void add(sp processToken, int32_t id, const sp& buffer); - sp get(sp processToken, int32_t id); + void add(const sp& processToken, uint64_t id, const sp& buffer); + void erase(const sp& processToken, uint64_t id); + + sp get(const sp& processToken, uint64_t id); void removeProcess(const wp& processToken); private: std::mutex mMutex; - std::map /*caching process*/, std::array, BUFFER_CACHE_MAX_SIZE>> + std::map /*caching process*/, std::map>> mBuffers GUARDED_BY(mMutex); class CacheDeathRecipient : public IBinder::DeathRecipient { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 55fcb01f3c..547f30f210 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3508,13 +3508,15 @@ bool SurfaceFlinger::flushTransactionQueues() { auto& [applyToken, transactionQueue] = *it; while (!transactionQueue.empty()) { - const auto& [states, displays, flags, desiredPresentTime, postTime, privileged] = - transactionQueue.front(); + const auto& + [states, displays, flags, desiredPresentTime, uncacheBuffer, postTime, + privileged] = transactionQueue.front(); if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) { break; } applyTransactionState(states, displays, flags, mPendingInputWindowCommands, - desiredPresentTime, postTime, privileged, /*isMainThread*/ true); + desiredPresentTime, uncacheBuffer, postTime, privileged, + /*isMainThread*/ true); transactionQueue.pop(); } @@ -3571,7 +3573,8 @@ void SurfaceFlinger::setTransactionState(const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime) { + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) { ATRACE_CALL(); const int64_t postTime = systemTime(); @@ -3588,20 +3591,22 @@ void SurfaceFlinger::setTransactionState(const Vector& states, if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() || !transactionIsReadyToBeApplied(desiredPresentTime, states)) { mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime, - postTime, privileged); + uncacheBuffer, postTime, privileged); setTransactionFlags(eTransactionNeeded); return; } applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime, - postTime, privileged); + uncacheBuffer, postTime, privileged); } void SurfaceFlinger::applyTransactionState(const Vector& states, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, - const int64_t desiredPresentTime, const int64_t postTime, - bool privileged, bool isMainThread) { + const int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer, + const int64_t postTime, bool privileged, + bool isMainThread) { uint32_t transactionFlags = 0; if (flags & eAnimation) { @@ -3636,6 +3641,10 @@ void SurfaceFlinger::applyTransactionState(const Vector& states, transactionFlags |= addInputWindowCommands(inputWindowCommands); + if (uncacheBuffer.token) { + BufferStateLayerCache::getInstance().erase(uncacheBuffer.token, uncacheBuffer.cacheId); + } + // If a synchronous transaction is explicitly requested without any changes, force a transaction // anyway. This can be used as a flush mechanism for previous async transactions. // Empty animation transaction can be used to simulate back-pressure, so also force a @@ -3977,16 +3986,20 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); } } - - if (what & layer_state_t::eBufferChanged) { - // Add the new buffer to the cache. This should always come before eCachedBufferChanged. - BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.bufferId, + bool bufferChanged = what & layer_state_t::eBufferChanged; + bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; + sp buffer; + if (bufferChanged && cacheIdChanged) { + BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.cacheId, s.buffer); - } - if (what & layer_state_t::eCachedBufferChanged) { - sp buffer = - BufferStateLayerCache::getInstance().get(s.cachedBuffer.token, - s.cachedBuffer.bufferId); + buffer = s.buffer; + } else if (cacheIdChanged) { + buffer = BufferStateLayerCache::getInstance().get(s.cachedBuffer.token, + s.cachedBuffer.cacheId); + } else if (bufferChanged) { + buffer = s.buffer; + } + if (buffer) { if (layer->setBuffer(buffer)) { flags |= eTraversalNeeded; layer->setPostTime(postTime); @@ -4230,7 +4243,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1); + setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}); setPowerModeInternal(display, HWC_POWER_MODE_NORMAL); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0776a1eb96..03146d6f17 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -431,7 +431,8 @@ private: const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime) override; + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) override; void bootFinished() override; bool authenticateSurfaceTexture( const sp& bufferProducer) const override; @@ -577,7 +578,8 @@ private: void applyTransactionState(const Vector& state, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, - const int64_t desiredPresentTime, const int64_t postTime, + const int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer, const int64_t postTime, bool privileged, bool isMainThread = false) REQUIRES(mStateLock); bool flushTransactionQueues(); uint32_t getTransactionFlags(uint32_t flags); @@ -1058,11 +1060,13 @@ private: struct TransactionState { TransactionState(const Vector& composerStates, const Vector& displayStates, uint32_t transactionFlags, - int64_t desiredPresentTime, int64_t postTime, bool privileged) + int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer, + int64_t postTime, bool privileged) : states(composerStates), displays(displayStates), flags(transactionFlags), desiredPresentTime(desiredPresentTime), + buffer(uncacheBuffer), postTime(postTime), privileged(privileged) {} @@ -1070,6 +1074,7 @@ private: Vector displays; uint32_t flags; const int64_t desiredPresentTime; + cached_buffer_t buffer; const int64_t postTime; bool privileged; }; -- cgit v1.2.3-59-g8ed1b From 48d7608aa5806192f18e2d572f56a6bc6a10a47c Mon Sep 17 00:00:00 2001 From: Yi Kong Date: Sun, 24 Mar 2019 02:01:06 -0700 Subject: [libs/ui] Modernize codebase by replacing NULL with nullptr Fixes -Wzero-as-null-pointer-constant warning. Test: m Bug: 68236239 Change-Id: I240d39ef4328943447149700b3ece371681078d1 --- libs/ui/Fence.cpp | 2 +- libs/ui/GraphicBuffer.cpp | 16 ++++++++-------- libs/ui/Region.cpp | 2 +- libs/ui/tools/lutgen.cpp | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp index ed7ccb0bed..4ce891e148 100644 --- a/libs/ui/Fence.cpp +++ b/libs/ui/Fence.cpp @@ -110,7 +110,7 @@ nsecs_t Fence::getSignalTime() const { } struct sync_file_info* finfo = sync_file_info(mFenceFd); - if (finfo == NULL) { + if (finfo == nullptr) { ALOGE("sync_file_info returned NULL for fd %d", mFenceFd.get()); return SIGNAL_TIME_INVALID; } diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index f800627ef7..a66dbc8527 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -76,7 +76,7 @@ GraphicBuffer::GraphicBuffer() usage_deprecated = 0; usage = 0; layerCount = 0; - handle = NULL; + handle = nullptr; } // deprecated @@ -143,7 +143,7 @@ void GraphicBuffer::free_handle() GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); allocator.free(handle); } - handle = NULL; + handle = nullptr; } status_t GraphicBuffer::initCheck() const { @@ -178,7 +178,7 @@ status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, if (handle) { GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); allocator.free(handle); - handle = 0; + handle = nullptr; } return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]"); } @@ -452,7 +452,7 @@ status_t GraphicBuffer::unflatten( width = height = stride = format = usage_deprecated = 0; layerCount = 0; usage = 0; - handle = NULL; + handle = nullptr; ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts); return BAD_VALUE; } @@ -486,7 +486,7 @@ status_t GraphicBuffer::unflatten( width = height = stride = format = usage_deprecated = 0; layerCount = 0; usage = 0; - handle = NULL; + handle = nullptr; ALOGE("unflatten: native_handle_create failed"); return NO_MEMORY; } @@ -497,7 +497,7 @@ status_t GraphicBuffer::unflatten( width = height = stride = format = usage_deprecated = 0; layerCount = 0; usage = 0; - handle = NULL; + handle = nullptr; } mId = static_cast(buf[7]) << 32; @@ -507,7 +507,7 @@ status_t GraphicBuffer::unflatten( mOwner = ownHandle; - if (handle != 0) { + if (handle != nullptr) { buffer_handle_t importedHandle; status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height), uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle); @@ -515,7 +515,7 @@ status_t GraphicBuffer::unflatten( width = height = stride = format = usage_deprecated = 0; layerCount = 0; usage = 0; - handle = NULL; + handle = nullptr; ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err); return err; } diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 3bd3748439..224dc2c122 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -820,7 +820,7 @@ status_t Region::unflatten(void const* buffer, size_t size) { } if (numRects > (UINT32_MAX / sizeof(Rect))) { - android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, NULL, 0); + android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, nullptr, 0); return NO_MEMORY; } diff --git a/libs/ui/tools/lutgen.cpp b/libs/ui/tools/lutgen.cpp index 97b0822238..85a1cebe7a 100644 --- a/libs/ui/tools/lutgen.cpp +++ b/libs/ui/tools/lutgen.cpp @@ -85,11 +85,11 @@ static const ColorSpace findColorSpace(const string& name) { static int handleCommandLineArgments(int argc, char* argv[]) { static constexpr const char* OPTSTR = "h:d:s:t:"; static const struct option OPTIONS[] = { - { "help", no_argument, 0, 'h' }, - { "dimension", required_argument, 0, 'd' }, - { "source", required_argument, 0, 's' }, - { "target", required_argument, 0, 't' }, - { 0, 0, 0, 0 } // termination of the option list + { "help", no_argument, nullptr, 'h' }, + { "dimension", required_argument, nullptr, 'd' }, + { "source", required_argument, nullptr, 's' }, + { "target", required_argument, nullptr, 't' }, + { nullptr, 0, nullptr, 0 } // termination of the option list }; int opt; -- cgit v1.2.3-59-g8ed1b From 69823cf333517befb84b172ba74c057192f9ac4d Mon Sep 17 00:00:00 2001 From: Tianyu Jiang Date: Mon, 25 Mar 2019 15:38:17 -0700 Subject: Clean up GraphicBuffer flatten and unflatten methods 1. Check size before accessing buf[0] in unflatten method 2. Remove unused params Test: GraphicBuffer_test Bug: 73550905 Change-Id: I25666ef37bba89a0033cfda81f85d85153ddea2a --- libs/ui/GraphicBuffer.cpp | 22 +++++++++------------- libs/ui/include/ui/GraphicBuffer.h | 5 ++--- 2 files changed, 11 insertions(+), 16 deletions(-) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 40df260fda..2fb1099f96 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -394,7 +394,7 @@ size_t GraphicBuffer::getFdCount() const { status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { #ifndef LIBUI_IN_VNDK if (mBufferHubBuffer != nullptr) { - return flattenBufferHubBuffer(buffer, size, fds, count); + return flattenBufferHubBuffer(buffer, size); } #endif size_t sizeNeeded = GraphicBuffer::getFlattenedSize(); @@ -437,6 +437,11 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) { + // Check if size is not smaller than buf[0] is supposed to take. + if (size < sizeof(int)) { + return NO_MEMORY; + } + int const* buf = static_cast(buffer); // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!! @@ -450,7 +455,7 @@ status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& flattenWordCount = 12; } else if (buf[0] == 'BHBB') { // BufferHub backed buffer. #ifndef LIBUI_IN_VNDK - return unflattenBufferHubBuffer(buffer, size, fds, count); + return unflattenBufferHubBuffer(buffer, size); #else return BAD_TYPE; #endif @@ -561,8 +566,7 @@ void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, v } #ifndef LIBUI_IN_VNDK -status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, - size_t& count) const { +status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size) const { sp tokenHandle = mBufferHubBuffer->duplicate(); if (tokenHandle == nullptr || tokenHandle->handle() == nullptr || tokenHandle->handle()->numFds != 0) { @@ -586,14 +590,10 @@ status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size, int* memcpy(buf + 2, tokenHandle->handle()->data, static_cast(numIntsInToken) * sizeof(int)); buf[2 + numIntsInToken] = static_cast(mGenerationNumber); - // Do not pass fds if it is BufferHubBuffer backed GraphicBuffer. Not modifying fds or count. - fds += 0; - count -= 0; return NO_ERROR; } -status_t GraphicBuffer::unflattenBufferHubBuffer(void const*& buffer, size_t& size, int const*& fds, - size_t& count) { +status_t GraphicBuffer::unflattenBufferHubBuffer(void const*& buffer, size_t& size) { const int* buf = static_cast(buffer); int numIntsInToken = buf[1]; // Size needed for one label, one number of ints inside the token, one generation number and @@ -627,10 +627,6 @@ status_t GraphicBuffer::unflattenBufferHubBuffer(void const*& buffer, size_t& si mBufferId = bufferHubBuffer->id(); mBufferHubBuffer.reset(std::move(bufferHubBuffer.get())); - // BufferHubBuffer backed GraphicBuffer does not have flattened handle. Not modifying fds or - // count. - fds += 0; - count -= 0; return NO_ERROR; } diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index c137860aee..c195342705 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -302,7 +302,7 @@ private: #ifndef LIBUI_IN_VNDK // Flatten this GraphicBuffer object if backed by BufferHubBuffer. - status_t flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, size_t& count) const; + status_t flattenBufferHubBuffer(void*& buffer, size_t& size) const; // Unflatten into BufferHubBuffer backed GraphicBuffer. // Unflatten will fail if the original GraphicBuffer object is destructed. For instance, a @@ -310,8 +310,7 @@ private: // to process/thread B through a socket, BufferHubBuffer_1 dies and bufferhub invalidated the // token. Race condition occurs between the invalidation of the token in bufferhub process and // process/thread B trying to unflatten and import the buffer with that token. - status_t unflattenBufferHubBuffer(void const*& buffer, size_t& size, int const*& fds, - size_t& count); + status_t unflattenBufferHubBuffer(void const*& buffer, size_t& size); // Stores a BufferHubBuffer that handles buffer signaling, identification. std::unique_ptr mBufferHubBuffer; -- cgit v1.2.3-59-g8ed1b From 5d2018a2e306030406c0f996d2b01adac7699afe Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 26 Mar 2019 15:07:54 -0700 Subject: Reallocate GraphicBuffer as long as the protected bit is different. Previously as long as the usage bit is the superset of the requested usage bit, we don't reallocate GraphicBuffer. However, this is wrong for protected contents, the protected usage bit on GraphicBuffer must align with the protected context. Since we turn off protected context when there's no protected content, we need to reallocate non-protected GraphicBuffer, otherwise it's undefined behaviour and will result in crash. BUG: b/35315015, b/127862411 Test: Verify no kgsl page fault with protected contents. Change-Id: I789076ba411079364528bd844e6abb5dcbfa77f7 --- libs/ui/GraphicBuffer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'libs/ui/GraphicBuffer.cpp') diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 40df260fda..45340a1fe9 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -194,6 +194,7 @@ bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight, if (inFormat != format) return true; if (inLayerCount != layerCount) return true; if ((usage & inUsage) != inUsage) return true; + if ((usage & USAGE_PROTECTED) != (inUsage & USAGE_PROTECTED)) return true; return false; } -- cgit v1.2.3-59-g8ed1b