From 79d13ff0f5cd3c4242445baf5b2f01a52f0ed06f Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 31 Mar 2017 12:48:11 -0700 Subject: [PATCH] graphics: revise gralloc interfaces Revise IAllocator and IMapper to reduce IPC and to support gralloc0 devices. Specifically, IAllocator is trimmed down to have essentially only allocate(BufferDescriptor descriptor, uint32_t count) generates (Error error, uint32_t stride, vec buffers); The ability to allocate buffers with shared backing store is removed. ProducerUsage and ConsumerUsage are moved to the graphics.common package and are merged and renamed to BufferUsage. BufferUsage's bits follow gralloc0. IMapper gains typedef vec BufferDescriptor; createDescriptor(BufferDescriptorInfo descriptorInfo) generates (Error error, BufferDescriptor descriptor); where BufferDescriptor is an implementation-defined blob. lockFlex is replaced by lockYCbCr. All getters are removed. Reference counting with retain/release is replaced by importBuffer/freeBuffer. Most if not all gralloc1 features are not used by the runtime yet. There is also not too much test written for them. As such, they tend to behave differently between implementations and cannot be used reliably. Bug: 36481301 Test: builds and boots on Pixel Change-Id: I1d31105120517ea2c128c7a19297acf3bfd312bb --- .../evs/1.0/vts/functional/FrameHandler.cpp | 78 +-- .../evs/1.0/vts/functional/FrameHandler.h | 2 - camera/device/1.0/Android.bp | 2 - .../1.0/ICameraDevicePreviewCallback.hal | 3 +- camera/device/1.0/default/CameraDevice.cpp | 4 +- camera/device/3.2/Android.bp | 2 - .../3.2/default/CameraDeviceSession.cpp | 3 +- camera/device/3.2/default/convert.cpp | 11 +- camera/device/3.2/types.hal | 10 +- camera/provider/2.4/Android.bp | 2 - .../VtsHalCameraProviderV2_4TargetTest.cpp | 6 +- graphics/Android.bp | 1 - graphics/allocator/2.0/Android.bp | 13 +- graphics/allocator/2.0/IAllocator.hal | 55 +- graphics/allocator/2.0/IAllocatorClient.hal | 165 ------ graphics/allocator/2.0/default/Android.bp | 3 +- graphics/allocator/2.0/default/Gralloc.cpp | 438 +------------- .../2.0/default/Gralloc0Allocator.cpp | 144 +++++ .../allocator/2.0/default/Gralloc0Allocator.h | 59 ++ .../2.0/default/Gralloc1Allocator.cpp | 321 +++++++++++ .../allocator/2.0/default/Gralloc1Allocator.h | 89 +++ graphics/allocator/2.0/types.hal | 148 ----- .../allocator/2.0/vts/functional/Android.bp | 62 -- .../VtsHalGraphicsAllocatorTestUtils.cpp | 183 ------ .../VtsHalGraphicsAllocatorTestUtils.h | 98 ---- .../VtsHalGraphicsAllocatorV2_0TargetTest.cpp | 186 ------ graphics/common/1.0/Android.mk | 38 ++ graphics/common/1.0/types.hal | 84 +++ .../composer/2.1/vts/functional/Android.bp | 1 - .../VtsHalGraphicsComposerV2_1TargetTest.cpp | 38 +- graphics/mapper/2.0/Android.bp | 2 - graphics/mapper/2.0/IMapper.hal | 342 ++++------- graphics/mapper/2.0/default/Android.bp | 9 +- .../mapper/2.0/default/Gralloc0Mapper.cpp | 156 +++++ graphics/mapper/2.0/default/Gralloc0Mapper.h | 56 ++ .../mapper/2.0/default/Gralloc1Mapper.cpp | 273 +++++++++ graphics/mapper/2.0/default/Gralloc1Mapper.h | 76 +++ .../2.0/default/GrallocBufferDescriptor.h | 79 +++ graphics/mapper/2.0/default/GrallocMapper.cpp | 540 +++++++----------- graphics/mapper/2.0/default/GrallocMapper.h | 66 +++ graphics/mapper/2.0/types.hal | 137 ++--- graphics/mapper/2.0/vts/functional/Android.bp | 2 - .../VtsHalGraphicsMapperTestUtils.cpp | 365 ++++++------ .../VtsHalGraphicsMapperTestUtils.h | 95 +-- .../VtsHalGraphicsMapperV2_0TargetTest.cpp | 468 ++++++++++----- 45 files changed, 2460 insertions(+), 2455 deletions(-) delete mode 100644 graphics/allocator/2.0/IAllocatorClient.hal create mode 100644 graphics/allocator/2.0/default/Gralloc0Allocator.cpp create mode 100644 graphics/allocator/2.0/default/Gralloc0Allocator.h create mode 100644 graphics/allocator/2.0/default/Gralloc1Allocator.cpp create mode 100644 graphics/allocator/2.0/default/Gralloc1Allocator.h delete mode 100644 graphics/allocator/2.0/types.hal delete mode 100644 graphics/allocator/2.0/vts/functional/Android.bp delete mode 100644 graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp delete mode 100644 graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h delete mode 100644 graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp create mode 100644 graphics/mapper/2.0/default/Gralloc0Mapper.cpp create mode 100644 graphics/mapper/2.0/default/Gralloc0Mapper.h create mode 100644 graphics/mapper/2.0/default/Gralloc1Mapper.cpp create mode 100644 graphics/mapper/2.0/default/Gralloc1Mapper.h create mode 100644 graphics/mapper/2.0/default/GrallocBufferDescriptor.h diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp index 01d9a0e304..58c2f262e3 100644 --- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp +++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include // std::min @@ -135,11 +134,7 @@ Return FrameHandler::deliverFrame(const BufferDesc& bufferArg) { // Local flag we use to keep track of when the stream is stopping bool timeToStop = false; - // TODO: Why do we get a gralloc crash if we don't clone the buffer here? - BufferDesc buffer(bufferArg); - ALOGD("Clone the received frame as %p", buffer.memHandle.getNativeHandle()); - - if (buffer.memHandle.getNativeHandle() == nullptr) { + if (bufferArg.memHandle.getNativeHandle() == nullptr) { // Signal that the last frame has been received and the stream is stopped timeToStop = true; } else { @@ -157,13 +152,8 @@ Return FrameHandler::deliverFrame(const BufferDesc& bufferArg) { printf("Didn't get target buffer - frame lost\n"); ALOGE("Didn't get requested output buffer -- skipping this frame."); } else { - // In order for the handles passed through HIDL and stored in the BufferDesc to - // be lockable, we must register them with GraphicBufferMapper - registerBufferHelper(tgtBuffer); - registerBufferHelper(buffer); - // Copy the contents of the of buffer.memHandle into tgtBuffer - copyBufferContents(tgtBuffer, buffer); + copyBufferContents(tgtBuffer, bufferArg); // Send the target buffer back for display Return result = mDisplay->returnTargetBufferForDisplay(tgtBuffer); @@ -183,10 +173,6 @@ Return FrameHandler::deliverFrame(const BufferDesc& bufferArg) { mFramesDisplayed++; mLock.unlock(); } - - // Now tell GraphicBufferMapper we won't be using these handles anymore - unregisterBufferHelper(tgtBuffer); - unregisterBufferHelper(buffer); } } @@ -233,24 +219,22 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer, const unsigned height = std::min(tgtBuffer.height, srcBuffer.height); - android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get(); - + sp tgt = new android::GraphicBuffer( + tgtBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE, + tgtBuffer.width, tgtBuffer.height, tgtBuffer.format, 1, tgtBuffer.usage, + tgtBuffer.stride); + sp src = new android::GraphicBuffer( + srcBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE, + srcBuffer.width, srcBuffer.height, srcBuffer.format, 1, srcBuffer.usage, + srcBuffer.stride); // Lock our source buffer for reading unsigned char* srcPixels = nullptr; - mapper.registerBuffer(srcBuffer.memHandle); - mapper.lock(srcBuffer.memHandle, - GRALLOC_USAGE_SW_READ_OFTEN, - android::Rect(width, height), - (void **) &srcPixels); + src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels); // Lock our target buffer for writing unsigned char* tgtPixels = nullptr; - mapper.registerBuffer(tgtBuffer.memHandle); - mapper.lock(tgtBuffer.memHandle, - GRALLOC_USAGE_SW_WRITE_OFTEN, - android::Rect(width, height), - (void **) &tgtPixels); + tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels); if (srcPixels && tgtPixels) { for (unsigned row = 0; row < height; row++) { @@ -267,45 +251,11 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer, } if (srcPixels) { - mapper.unlock(srcBuffer.memHandle); + src->unlock(); } if (tgtPixels) { - mapper.unlock(tgtBuffer.memHandle); + tgt->unlock(); } - mapper.unregisterBuffer(srcBuffer.memHandle); - mapper.unregisterBuffer(tgtBuffer.memHandle); return success; } - - -void FrameHandler::registerBufferHelper(const BufferDesc& buffer) -{ - // In order for the handles passed through HIDL and stored in the BufferDesc to - // be lockable, we must register them with GraphicBufferMapper. - // If the device upon which we're running supports gralloc1, we could just call - // registerBuffer directly with the handle. But that call is broken for gralloc0 devices - // (which we care about, at least for now). As a result, we have to synthesize a GraphicBuffer - // object around the buffer handle in order to make a call to the overloaded alternate - // version of the registerBuffer call that does happen to work on gralloc0 devices. -#if REGISTER_BUFFER_ALWAYS_WORKS - android::GraphicBufferMapper::get().registerBuffer(buffer.memHandle); -#else - android::sp pGfxBuff = new android::GraphicBuffer( - buffer.width, buffer.height, buffer.format, - 1, /* we always use exactly one layer */ - buffer.usage, buffer.stride, - const_cast(buffer.memHandle.getNativeHandle()), - false /* GraphicBuffer should not try to free the handle */ - ); - - android::GraphicBufferMapper::get().registerBuffer(pGfxBuff.get()); -#endif -} - - -void FrameHandler::unregisterBufferHelper(const BufferDesc& buffer) -{ - // Now tell GraphicBufferMapper we won't be using these handles anymore - android::GraphicBufferMapper::get().unregisterBuffer(buffer.memHandle); -} diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.h b/automotive/evs/1.0/vts/functional/FrameHandler.h index d5c3f6bfde..17a39803fa 100644 --- a/automotive/evs/1.0/vts/functional/FrameHandler.h +++ b/automotive/evs/1.0/vts/functional/FrameHandler.h @@ -68,8 +68,6 @@ private: // Local implementation details bool copyBufferContents(const BufferDesc& tgtBuffer, const BufferDesc& srcBuffer); - void registerBufferHelper(const BufferDesc& buffer); - void unregisterBufferHelper(const BufferDesc& buffer); // Values initialized as startup android::sp mCamera; diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp index 44a108ce29..81e41aa0af 100644 --- a/camera/device/1.0/Android.bp +++ b/camera/device/1.0/Android.bp @@ -66,7 +66,6 @@ cc_library_shared { "libutils", "libcutils", "android.hardware.camera.common@1.0", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], @@ -76,7 +75,6 @@ cc_library_shared { "libhwbinder", "libutils", "android.hardware.camera.common@1.0", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], diff --git a/camera/device/1.0/ICameraDevicePreviewCallback.hal b/camera/device/1.0/ICameraDevicePreviewCallback.hal index 4c9b517265..54219811fc 100644 --- a/camera/device/1.0/ICameraDevicePreviewCallback.hal +++ b/camera/device/1.0/ICameraDevicePreviewCallback.hal @@ -17,7 +17,6 @@ package android.hardware.camera.device@1.0; import android.hardware.camera.common@1.0::types; -import android.hardware.graphics.allocator@2.0::types; import android.hardware.graphics.common@1.0::types; /** @@ -89,7 +88,7 @@ interface ICameraDevicePreviewCallback { * * @return Status The status code for this operation. */ - setUsage(ProducerUsage usage) generates (Status status); + setUsage(BufferUsage usage) generates (Status status); /** * Set the expected buffering mode for the preview output. diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp index 6495f30222..cb20fec80f 100644 --- a/camera/device/1.0/default/CameraDevice.cpp +++ b/camera/device/1.0/default/CameraDevice.cpp @@ -30,7 +30,7 @@ namespace device { namespace V1_0 { namespace implementation { -using ::android::hardware::graphics::allocator::V2_0::ProducerUsage; +using ::android::hardware::graphics::common::V1_0::BufferUsage; using ::android::hardware::graphics::common::V1_0::PixelFormat; HandleImporter& CameraDevice::sHandleImporter = HandleImporter::getInstance(); @@ -259,7 +259,7 @@ int CameraDevice::sSetUsage(struct preview_stream_ops* w, int usage) { } object->cleanUpCirculatingBuffers(); - return getStatusT(object->mPreviewCallback->setUsage((ProducerUsage) usage)); + return getStatusT(object->mPreviewCallback->setUsage((BufferUsage)usage)); } int CameraDevice::sSetSwapInterval(struct preview_stream_ops *w, int interval) { diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp index fd7276f946..7807a857aa 100644 --- a/camera/device/3.2/Android.bp +++ b/camera/device/3.2/Android.bp @@ -66,7 +66,6 @@ cc_library_shared { "libutils", "libcutils", "android.hardware.camera.common@1.0", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], @@ -76,7 +75,6 @@ cc_library_shared { "libhwbinder", "libutils", "android.hardware.camera.common@1.0", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp index 5b3024b238..5bb53c7d5f 100644 --- a/camera/device/3.2/default/CameraDeviceSession.cpp +++ b/camera/device/3.2/default/CameraDeviceSession.cpp @@ -650,7 +650,8 @@ Return CameraDeviceSession::configureStreams( mVideoStreamIds.clear(); for (const auto& stream : requestedConfiguration.streams) { if (stream.streamType == StreamType::OUTPUT && - stream.usage & graphics::allocator::V2_0::ConsumerUsage::VIDEO_ENCODER) { + stream.usage & + graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) { mVideoStreamIds.push_back(stream.id); } } diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp index c7cc75ad4d..d878deb03d 100644 --- a/camera/device/3.2/default/convert.cpp +++ b/camera/device/3.2/default/convert.cpp @@ -28,8 +28,7 @@ namespace implementation { using ::android::hardware::graphics::common::V1_0::Dataspace; using ::android::hardware::graphics::common::V1_0::PixelFormat; -using ::android::hardware::camera::device::V3_2::ConsumerUsageFlags; -using ::android::hardware::camera::device::V3_2::ProducerUsageFlags; +using ::android::hardware::camera::device::V3_2::BufferUsageFlags; bool convertFromHidl(const CameraMetadata &src, const camera_metadata_t** dst) { if (src.size() == 0) { @@ -78,11 +77,11 @@ void convertToHidl(const Camera3Stream* src, HalStream* dst) { dst->overrideFormat = (PixelFormat) src->format; dst->maxBuffers = src->max_buffers; if (src->stream_type == CAMERA3_STREAM_OUTPUT) { - dst->consumerUsage = (ConsumerUsageFlags) 0; - dst->producerUsage = (ProducerUsageFlags) src->usage; + dst->consumerUsage = (BufferUsageFlags)0; + dst->producerUsage = (BufferUsageFlags)src->usage; } else if (src->stream_type == CAMERA3_STREAM_INPUT) { - dst->producerUsage = (ProducerUsageFlags) 0; - dst->consumerUsage = (ConsumerUsageFlags) src->usage; + dst->producerUsage = (BufferUsageFlags)0; + dst->consumerUsage = (BufferUsageFlags)src->usage; } else { //Should not reach here per current HIDL spec, but we might end up adding // bi-directional stream to HIDL. diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal index 5ae7a18c39..1632570953 100644 --- a/camera/device/3.2/types.hal +++ b/camera/device/3.2/types.hal @@ -16,12 +16,10 @@ package android.hardware.camera.device@3.2; -import android.hardware.graphics.allocator@2.0::types; import android.hardware.graphics.common@1.0::types; typedef vec CameraMetadata; -typedef bitfield ProducerUsageFlags; -typedef bitfield ConsumerUsageFlags; +typedef bitfield BufferUsageFlags; typedef bitfield DataspaceFlags; /** @@ -255,7 +253,7 @@ struct Stream { * with ILLEGAL_ARGUMENT if the combined flags cannot be supported due to * imcompatible buffer format, dataSpace, or other hardware limitations. */ - ConsumerUsageFlags usage; + BufferUsageFlags usage; /** * A field that describes the contents of the buffer. The format and buffer @@ -373,8 +371,8 @@ struct HalStream { * consumerUsage must be set. For other types, producerUsage must be set, * and consumerUsage must be 0. */ - ProducerUsageFlags producerUsage; - ConsumerUsageFlags consumerUsage; + BufferUsageFlags producerUsage; + BufferUsageFlags consumerUsage; /** * The maximum number of buffers the HAL device may need to have dequeued at diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp index 1656325edc..d295f3e0b5 100644 --- a/camera/provider/2.4/Android.bp +++ b/camera/provider/2.4/Android.bp @@ -57,7 +57,6 @@ cc_library_shared { "android.hardware.camera.common@1.0", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], @@ -69,7 +68,6 @@ cc_library_shared { "android.hardware.camera.common@1.0", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 74e6efe6dc..e37f989c58 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -52,8 +52,8 @@ using ::android::BufferQueue; using ::android::BufferItemConsumer; using ::android::Surface; using ::android::CameraParameters; +using ::android::hardware::graphics::common::V1_0::BufferUsage; using ::android::hardware::graphics::common::V1_0::PixelFormat; -using ::android::hardware::graphics::allocator::V2_0::ProducerUsage; using ::android::hardware::camera::common::V1_0::Status; using ::android::hardware::camera::common::V1_0::CameraDeviceStatus; using ::android::hardware::camera::common::V1_0::TorchMode; @@ -233,7 +233,7 @@ struct PreviewWindowCb : public ICameraDevicePreviewCallback { Return setCrop(int32_t left, int32_t top, int32_t right, int32_t bottom) override; - Return setUsage(ProducerUsage usage) override; + Return setUsage(BufferUsage usage) override; Return setSwapInterval(int32_t interval) override; @@ -408,7 +408,7 @@ Return PreviewWindowCb::setCrop(int32_t left, int32_t top, return mapToStatus(rc); } -Return PreviewWindowCb::setUsage(ProducerUsage usage) { +Return PreviewWindowCb::setUsage(BufferUsage usage) { auto rc = native_window_set_usage(mAnw.get(), static_cast(usage)); if (rc == ::android::OK) { mPreviewUsage = static_cast(usage); diff --git a/graphics/Android.bp b/graphics/Android.bp index f4f7db46d9..9aea85f6c4 100644 --- a/graphics/Android.bp +++ b/graphics/Android.bp @@ -2,7 +2,6 @@ subdirs = [ "allocator/2.0", "allocator/2.0/default", - "allocator/2.0/vts/functional", "bufferqueue/1.0", "common/1.0", "composer/2.1", diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp index 271f2cecbc..f707468d25 100644 --- a/graphics/allocator/2.0/Android.bp +++ b/graphics/allocator/2.0/Android.bp @@ -3,9 +3,7 @@ filegroup { name: "android.hardware.graphics.allocator@2.0_hal", srcs: [ - "types.hal", "IAllocator.hal", - "IAllocatorClient.hal", ], } @@ -17,9 +15,7 @@ genrule { ":android.hardware.graphics.allocator@2.0_hal", ], out: [ - "android/hardware/graphics/allocator/2.0/types.cpp", "android/hardware/graphics/allocator/2.0/AllocatorAll.cpp", - "android/hardware/graphics/allocator/2.0/AllocatorClientAll.cpp", ], } @@ -31,18 +27,11 @@ genrule { ":android.hardware.graphics.allocator@2.0_hal", ], out: [ - "android/hardware/graphics/allocator/2.0/types.h", - "android/hardware/graphics/allocator/2.0/hwtypes.h", "android/hardware/graphics/allocator/2.0/IAllocator.h", "android/hardware/graphics/allocator/2.0/IHwAllocator.h", "android/hardware/graphics/allocator/2.0/BnHwAllocator.h", "android/hardware/graphics/allocator/2.0/BpHwAllocator.h", "android/hardware/graphics/allocator/2.0/BsAllocator.h", - "android/hardware/graphics/allocator/2.0/IAllocatorClient.h", - "android/hardware/graphics/allocator/2.0/IHwAllocatorClient.h", - "android/hardware/graphics/allocator/2.0/BnHwAllocatorClient.h", - "android/hardware/graphics/allocator/2.0/BpHwAllocatorClient.h", - "android/hardware/graphics/allocator/2.0/BsAllocatorClient.h", ], } @@ -59,6 +48,7 @@ cc_library_shared { "libutils", "libcutils", "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", "android.hidl.base@1.0", ], export_shared_lib_headers: [ @@ -67,6 +57,7 @@ cc_library_shared { "libhwbinder", "libutils", "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", "android.hidl.base@1.0", ], } diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal index bf0e141729..43a39169a8 100644 --- a/graphics/allocator/2.0/IAllocator.hal +++ b/graphics/allocator/2.0/IAllocator.hal @@ -16,38 +16,9 @@ package android.hardware.graphics.allocator@2.0; -import IAllocatorClient; +import android.hardware.graphics.mapper@2.0; interface IAllocator { - enum Capability : int32_t { - /** reserved */ - INVALID = 0, - - /** - * IAllocatorClient::testAllocate must always return UNDEFINED unless - * this capability is supported. - */ - TEST_ALLOCATE = 1, - - /** - * IAllocatorClient::BufferDescriptorInfo::layerCount must be 1 unless - * this capability is supported. - */ - LAYERED_BUFFERS = 2, - }; - - /** - * Provides a list of supported capabilities (as described in the - * definition of Capability above). This list must not change after - * initialization. - * - * @return capabilities is a list of supported capabilities. - */ - @entry - @exit - @callflow(next="*") - getCapabilities() generates (vec capabilities); - /** * Retrieves implementation-defined debug information, which will be * displayed during, for example, `dumpsys SurfaceFlinger`. @@ -60,15 +31,27 @@ interface IAllocator { dumpDebugInfo() generates (string debugInfo); /** - * Creates a client of the allocator. All resources created by the client - * are owned by the client and are only visible to the client, unless they - * are exported by exportHandle. + * Allocates buffers with the properties specified by the descriptor. * + * @param descriptor specifies the properties of the buffers to allocate. + * @param count is the number of buffers to allocate. * @return error is NONE upon success. Otherwise, - * NO_RESOURCES when no more client can currently be created. - * @return client is the newly created client. + * BAD_DESCRIPTOR when the descriptor is invalid. + * NO_RESOURCES when the allocation cannot be fulfilled at this + * time. + * UNSUPPORTED when any of the property encoded in the descriptor + * is not supported. + * @return stride is the number of pixels between two consecutive rows of + * the buffers, when the concept of consecutive rows is defined. + * Otherwise, it has no meaning. + * @return buffers is an array of raw handles to the newly allocated + * buffers. */ @entry + @exit @callflow(next="*") - createClient() generates (Error error, IAllocatorClient client); + allocate(BufferDescriptor descriptor, uint32_t count) + generates (Error error, + uint32_t stride, + vec buffers); }; diff --git a/graphics/allocator/2.0/IAllocatorClient.hal b/graphics/allocator/2.0/IAllocatorClient.hal deleted file mode 100644 index 8ca568f275..0000000000 --- a/graphics/allocator/2.0/IAllocatorClient.hal +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -package android.hardware.graphics.allocator@2.0; - -import android.hardware.graphics.common@1.0::PixelFormat; - -interface IAllocatorClient { - struct BufferDescriptorInfo { - /** - * The width specifies how many columns of pixels must be in the - * allocated buffer, but does not necessarily represent the offset in - * columns between the same column in adjacent rows. The rows may be - * padded. - */ - uint32_t width; - - /** - * The height specifies how many rows of pixels must be in the - * allocated buffer. - */ - uint32_t height; - - /** - * The number of image layers that must be in the allocated buffer. - */ - uint32_t layerCount; - - /** Buffer pixel format. */ - PixelFormat format; - - /** - * Buffer producer usage mask; valid flags can be found in the - * definition of ProducerUsage. - */ - uint64_t producerUsageMask; - - /** - * Buffer consumer usage mask; valid flags can be found in the - * definition of ConsumerUsage. - */ - uint64_t consumerUsageMask; - }; - - /** - * Creates a new, opaque buffer descriptor. - * - * @param descriptorInfo specifies the attributes of the buffer - * descriptor. - * @return error is NONE upon success. Otherwise, - * BAD_VALUE when any attribute in descriptorInfo is invalid. - * NO_RESOURCES when no more descriptors can currently be created. - * @return descriptor is the newly created buffer descriptor. - */ - @entry - @callflow(next="*") - createDescriptor(BufferDescriptorInfo descriptorInfo) - generates (Error error, - BufferDescriptor descriptor); - - /** - * Destroys an existing buffer descriptor. - * - * @param descriptor is the descriptor to destroy. - * @return error is either NONE or BAD_DESCRIPTOR. - */ - @exit - @callflow(next="*") - destroyDescriptor(BufferDescriptor descriptor) generates (Error error); - - /** - * Tests whether a buffer allocation can succeed, ignoring potential - * resource contention which might lead to a NO_RESOURCES error. - * - * @param descriptors is a list of buffer descriptors. - * @return error is NONE or NOT_SHARED upon success; - * NONE when buffers can be created and share a backing store. - * NOT_SHARED when buffers can be created but require more than a - * backing store. - * Otherwise, - * BAD_DESCRIPTOR when any of the descriptors is invalid. - * UNSUPPORTED when any of the descriptors can never be satisfied. - * UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities. - */ - @callflow(next="allocate") - testAllocate(vec descriptors) generates (Error error); - - /** - * Attempts to allocate a list of buffers sharing a backing store. - * - * Each buffer must correspond to one of the descriptors passed into the - * function and must hold a reference to its backing store. If the device - * is unable to share the backing store between the buffers, it must - * attempt to allocate the buffers with different backing stores and - * return NOT_SHARED if it is successful. - * - * @param descriptors is the buffer descriptors to attempt to allocate. - * @return error is NONE or NOT_SHARED upon success; - * NONE when buffers can be created and share a backing store. - * NOT_SHARED when buffers can be created but require more than a - * backing store. - * Otherwise, - * BAD_DESCRIPTOR when any of the descriptors is invalid. - * UNSUPPORTED when any of the descriptors can never be satisfied. - * NO_RESOURCES when any of the buffers cannot be created at this - * time. - * @return buffers is the allocated buffers. - */ - @callflow(next="exportHandle") - allocate(vec descriptors) - generates (Error error, - vec buffers); - - /** - * Frees a buffer. - * - * @param buffer is the buffer to be freed. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer is invalid. - */ - @exit - @callflow(next="*") - free(Buffer buffer) generates (Error error); - - /** - * Exports a buffer for use in other client libraries or for cross-process - * sharing. - * - * The exported handle is a handle to the backing store of the buffer, not - * to the buffer itself. It however may not hold any reference to the - * backing store and may be considered invalid by client libraries. To use - * it and, in most cases, to save it for later use, a client must make a - * clone of the handle and have the cloned handle hold a reference to the - * backing store. Such a cloned handle will stay valid even after the - * original buffer is freed. Refer to native_handle_clone and IMapper for - * how a handle is cloned and how a reference is added. - * - * @param descriptor is the descriptor used to allocate the buffer. - * @param buffer is the buffer to be exported. - * @return error is NONE upon success. Otherwise, - * BAD_DESCRIPTOR when the descriptor is invalid. - * BAD_BUFFER when the buffer is invalid. - * BAD_VALUE when descriptor and buffer do not match. - * NO_RESOURCES when the buffer cannot be exported at this time. - * @return bufferHandle is the exported handle. - */ - @callflow(next="free") - exportHandle(BufferDescriptor descriptor, - Buffer buffer) - generates (Error error, - handle bufferHandle); -}; diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp index 0baef89308..6adfa71f7b 100644 --- a/graphics/allocator/2.0/default/Android.bp +++ b/graphics/allocator/2.0/default/Android.bp @@ -3,7 +3,7 @@ cc_library_shared { defaults: ["hidl_defaults"], proprietary: true, relative_install_path: "hw", - srcs: ["Gralloc.cpp"], + srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"], cppflags: ["-Wall", "-Wextra"], shared_libs: [ "android.hardware.graphics.allocator@2.0", @@ -15,6 +15,7 @@ cc_library_shared { "liblog", "libutils", ], + static_libs: ["libgrallocmapperincludes"], } cc_binary { diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp index 0b9e863eb5..273d3f5843 100644 --- a/graphics/allocator/2.0/default/Gralloc.cpp +++ b/graphics/allocator/2.0/default/Gralloc.cpp @@ -16,17 +16,11 @@ #define LOG_TAG "GrallocPassthrough" -#include -#include -#include -#include - -#include - -#include -#include - #include "Gralloc.h" +#include "Gralloc0Allocator.h" +#include "Gralloc1Allocator.h" + +#include namespace android { namespace hardware { @@ -35,417 +29,6 @@ namespace allocator { namespace V2_0 { namespace implementation { -class GrallocHal : public IAllocator { -public: - GrallocHal(const hw_module_t* module); - virtual ~GrallocHal(); - - // IAllocator interface - Return getCapabilities(getCapabilities_cb hidl_cb) override; - Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; - Return createClient(createClient_cb hidl_cb) override; - - Error createDescriptor( - const IAllocatorClient::BufferDescriptorInfo& descriptorInfo, - BufferDescriptor* outDescriptor); - Error destroyDescriptor(BufferDescriptor descriptor); - - Error testAllocate(const hidl_vec& descriptors); - Error allocate(const hidl_vec& descriptors, - hidl_vec* outBuffers); - Error free(Buffer buffer); - - Error exportHandle(Buffer buffer, const native_handle_t** outHandle); - -private: - void initCapabilities(); - - template - void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn); - void initDispatch(); - - bool hasCapability(Capability capability) const; - - gralloc1_device_t* mDevice; - - std::unordered_set mCapabilities; - - struct { - GRALLOC1_PFN_DUMP dump; - GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor; - GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor; - GRALLOC1_PFN_SET_DIMENSIONS setDimensions; - GRALLOC1_PFN_SET_FORMAT setFormat; - GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount; - GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage; - GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage; - GRALLOC1_PFN_ALLOCATE allocate; - GRALLOC1_PFN_RELEASE release; - } mDispatch; -}; - -class GrallocClient : public IAllocatorClient { -public: - GrallocClient(GrallocHal& hal); - virtual ~GrallocClient(); - - // IAllocatorClient interface - Return createDescriptor(const BufferDescriptorInfo& descriptorInfo, - createDescriptor_cb hidl_cb) override; - Return destroyDescriptor(BufferDescriptor descriptor) override; - - Return testAllocate( - const hidl_vec& descriptors) override; - Return allocate(const hidl_vec& descriptors, - allocate_cb hidl_cb) override; - Return free(Buffer buffer) override; - - Return exportHandle(BufferDescriptor descriptor, - Buffer buffer, exportHandle_cb hidl_cb) override; - -private: - GrallocHal& mHal; - - std::mutex mMutex; - std::unordered_set mDescriptors; - std::unordered_set mBuffers; -}; - -GrallocHal::GrallocHal(const hw_module_t* module) - : mDevice(nullptr), mDispatch() -{ - int status = gralloc1_open(module, &mDevice); - if (status) { - LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s", - strerror(-status)); - } - - initCapabilities(); - initDispatch(); -} - -GrallocHal::~GrallocHal() -{ - gralloc1_close(mDevice); -} - -void GrallocHal::initCapabilities() -{ - uint32_t count = 0; - mDevice->getCapabilities(mDevice, &count, nullptr); - - std::vector caps(count); - mDevice->getCapabilities(mDevice, &count, reinterpret_cast< - std::underlying_type::type*>(caps.data())); - caps.resize(count); - - mCapabilities.insert(caps.cbegin(), caps.cend()); -} - -template -void GrallocHal::initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) -{ - auto pfn = mDevice->getFunction(mDevice, desc); - if (!pfn) { - LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc); - } - - *outPfn = reinterpret_cast(pfn); -} - -void GrallocHal::initDispatch() -{ - initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump); - initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, - &mDispatch.createDescriptor); - initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, - &mDispatch.destroyDescriptor); - initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions); - initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat); - if (hasCapability(Capability::LAYERED_BUFFERS)) { - initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT, - &mDispatch.setLayerCount); - } - initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, - &mDispatch.setConsumerUsage); - initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, - &mDispatch.setProducerUsage); - initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate); - initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release); -} - -bool GrallocHal::hasCapability(Capability capability) const -{ - return (mCapabilities.count(capability) > 0); -} - -Return GrallocHal::getCapabilities(getCapabilities_cb hidl_cb) -{ - std::vector caps( - mCapabilities.cbegin(), mCapabilities.cend()); - - hidl_vec reply; - reply.setToExternal(caps.data(), caps.size()); - hidl_cb(reply); - - return Void(); -} - -Return GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) -{ - uint32_t len = 0; - mDispatch.dump(mDevice, &len, nullptr); - - std::vector buf(len + 1); - mDispatch.dump(mDevice, &len, buf.data()); - buf.resize(len + 1); - buf[len] = '\0'; - - hidl_string reply; - reply.setToExternal(buf.data(), len); - hidl_cb(reply); - - return Void(); -} - -Return GrallocHal::createClient(createClient_cb hidl_cb) -{ - sp client = new GrallocClient(*this); - hidl_cb(Error::NONE, client); - - return Void(); -} - -Error GrallocHal::createDescriptor( - const IAllocatorClient::BufferDescriptorInfo& descriptorInfo, - BufferDescriptor* outDescriptor) -{ - gralloc1_buffer_descriptor_t descriptor; - int32_t err = mDispatch.createDescriptor(mDevice, &descriptor); - if (err != GRALLOC1_ERROR_NONE) { - return static_cast(err); - } - - err = mDispatch.setDimensions(mDevice, descriptor, - descriptorInfo.width, descriptorInfo.height); - if (err == GRALLOC1_ERROR_NONE) { - err = mDispatch.setFormat(mDevice, descriptor, - static_cast(descriptorInfo.format)); - } - if (err == GRALLOC1_ERROR_NONE) { - if (hasCapability(Capability::LAYERED_BUFFERS)) { - err = mDispatch.setLayerCount(mDevice, descriptor, - descriptorInfo.layerCount); - } else if (descriptorInfo.layerCount != 1) { - err = GRALLOC1_ERROR_BAD_VALUE; - } - } - if (err == GRALLOC1_ERROR_NONE) { - uint64_t producerUsageMask = descriptorInfo.producerUsageMask; - if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) { - producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ; - } - if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) { - producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE; - } - err = mDispatch.setProducerUsage(mDevice, descriptor, - descriptorInfo.producerUsageMask); - } - if (err == GRALLOC1_ERROR_NONE) { - uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask; - if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) { - consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ; - } - err = mDispatch.setConsumerUsage(mDevice, descriptor, - consumerUsageMask); - } - - if (err == GRALLOC1_ERROR_NONE) { - *outDescriptor = descriptor; - } else { - mDispatch.destroyDescriptor(mDevice, descriptor); - } - - return static_cast(err); -} - -Error GrallocHal::destroyDescriptor(BufferDescriptor descriptor) -{ - int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor); - return static_cast(err); -} - -Error GrallocHal::testAllocate(const hidl_vec& descriptors) -{ - if (!hasCapability(Capability::TEST_ALLOCATE)) { - return Error::UNDEFINED; - } - - int32_t err = mDispatch.allocate(mDevice, descriptors.size(), - descriptors.data(), nullptr); - return static_cast(err); -} - -Error GrallocHal::allocate(const hidl_vec& descriptors, - hidl_vec* outBuffers) -{ - std::vector buffers(descriptors.size()); - int32_t err = mDispatch.allocate(mDevice, descriptors.size(), - descriptors.data(), buffers.data()); - if (err == GRALLOC1_ERROR_NONE || err == GRALLOC1_ERROR_NOT_SHARED) { - outBuffers->resize(buffers.size()); - for (size_t i = 0; i < outBuffers->size(); i++) { - (*outBuffers)[i] = static_cast( - reinterpret_cast(buffers[i])); - } - } - - return static_cast(err); -} - -Error GrallocHal::free(Buffer buffer) -{ - buffer_handle_t handle = reinterpret_cast( - static_cast(buffer)); - - int32_t err = mDispatch.release(mDevice, handle); - return static_cast(err); -} - -Error GrallocHal::exportHandle(Buffer buffer, - const native_handle_t** outHandle) -{ - // we rely on the caller to validate buffer here - *outHandle = reinterpret_cast( - static_cast(buffer)); - return Error::NONE; -} - -GrallocClient::GrallocClient(GrallocHal& hal) - : mHal(hal) -{ -} - -GrallocClient::~GrallocClient() -{ - if (!mBuffers.empty()) { - ALOGW("client destroyed with valid buffers"); - for (auto buf : mBuffers) { - mHal.free(buf); - } - } - - if (!mDescriptors.empty()) { - ALOGW("client destroyed with valid buffer descriptors"); - for (auto desc : mDescriptors) { - mHal.destroyDescriptor(desc); - } - } -} - -Return GrallocClient::createDescriptor( - const BufferDescriptorInfo& descriptorInfo, - createDescriptor_cb hidl_cb) -{ - BufferDescriptor descriptor = 0; - Error err = mHal.createDescriptor(descriptorInfo, &descriptor); - - if (err == Error::NONE) { - std::lock_guard lock(mMutex); - - auto result = mDescriptors.insert(descriptor); - if (!result.second) { - ALOGW("duplicated buffer descriptor id returned"); - mHal.destroyDescriptor(descriptor); - err = Error::NO_RESOURCES; - } - } - - hidl_cb(err, descriptor); - return Void(); -} - -Return GrallocClient::destroyDescriptor(BufferDescriptor descriptor) -{ - { - std::lock_guard lock(mMutex); - if (!mDescriptors.erase(descriptor)) { - return Error::BAD_DESCRIPTOR; - } - } - - return mHal.destroyDescriptor(descriptor); -} - -Return GrallocClient::testAllocate( - const hidl_vec& descriptors) -{ - return mHal.testAllocate(descriptors); -} - -Return GrallocClient::allocate( - const hidl_vec& descriptors, - allocate_cb hidl_cb) { - hidl_vec buffers; - Error err = mHal.allocate(descriptors, &buffers); - - if (err == Error::NONE || err == Error::NOT_SHARED) { - std::lock_guard lock(mMutex); - - for (size_t i = 0; i < buffers.size(); i++) { - auto result = mBuffers.insert(buffers[i]); - if (!result.second) { - ALOGW("duplicated buffer id returned"); - - for (size_t j = 0; j < buffers.size(); j++) { - if (j < i) { - mBuffers.erase(buffers[i]); - } - mHal.free(buffers[i]); - } - - buffers = hidl_vec(); - err = Error::NO_RESOURCES; - break; - } - } - } - - hidl_cb(err, buffers); - return Void(); -} - -Return GrallocClient::free(Buffer buffer) -{ - { - std::lock_guard lock(mMutex); - if (!mBuffers.erase(buffer)) { - return Error::BAD_BUFFER; - } - } - - return mHal.free(buffer); -} - -Return GrallocClient::exportHandle(BufferDescriptor /*descriptor*/, - Buffer buffer, exportHandle_cb hidl_cb) -{ - const native_handle_t* handle = nullptr; - - { - std::lock_guard lock(mMutex); - if (mBuffers.count(buffer) == 0) { - hidl_cb(Error::BAD_BUFFER, handle); - return Void(); - } - } - - Error err = mHal.exportHandle(buffer, &handle); - - hidl_cb(err, handle); - return Void(); -} - IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) { const hw_module_t* module = nullptr; int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); @@ -455,12 +38,15 @@ IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) { } uint8_t major = (module->module_api_version >> 8) & 0xff; - if (major != 1) { - ALOGE("unknown gralloc module major version %d", major); - return nullptr; + switch (major) { + case 1: + return new Gralloc1Allocator(module); + case 0: + return new Gralloc0Allocator(module); + default: + ALOGE("unknown gralloc module major version %d", major); + return nullptr; } - - return new GrallocHal(module); } } // namespace implementation diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp new file mode 100644 index 0000000000..3b62bb3191 --- /dev/null +++ b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2016 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 "Gralloc0Allocator" + +#include "Gralloc0Allocator.h" +#include "GrallocBufferDescriptor.h" + +#include + +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::mapper::V2_0::implementation:: + grallocDecodeBufferDescriptor; + +Gralloc0Allocator::Gralloc0Allocator(const hw_module_t* module) { + int result = gralloc_open(module, &mDevice); + if (result) { + LOG_ALWAYS_FATAL("failed to open gralloc0 device: %s", + strerror(-result)); + } +} + +Gralloc0Allocator::~Gralloc0Allocator() { + gralloc_close(mDevice); +} + +Return Gralloc0Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) { + char buf[4096] = {}; + if (mDevice->dump) { + mDevice->dump(mDevice, buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + } + + hidl_cb(hidl_string(buf)); + + return Void(); +} + +Return Gralloc0Allocator::allocate(const BufferDescriptor& descriptor, + uint32_t count, allocate_cb hidl_cb) { + IMapper::BufferDescriptorInfo descriptorInfo; + if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) { + hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec()); + return Void(); + } + + Error error = Error::NONE; + uint32_t stride = 0; + std::vector buffers; + buffers.reserve(count); + + // allocate the buffers + for (uint32_t i = 0; i < count; i++) { + buffer_handle_t tmpBuffer; + uint32_t tmpStride; + error = allocateOne(descriptorInfo, &tmpBuffer, &tmpStride); + if (error != Error::NONE) { + break; + } + + if (stride == 0) { + stride = tmpStride; + } else if (stride != tmpStride) { + // non-uniform strides + mDevice->free(mDevice, tmpBuffer); + stride = 0; + error = Error::UNSUPPORTED; + break; + } + + buffers.emplace_back(hidl_handle(tmpBuffer)); + } + + // return the buffers + hidl_vec hidl_buffers; + if (error == Error::NONE) { + hidl_buffers.setToExternal(buffers.data(), buffers.size()); + } + hidl_cb(error, stride, hidl_buffers); + + // free the buffers + for (const auto& buffer : buffers) { + mDevice->free(mDevice, buffer.getNativeHandle()); + } + + return Void(); +} + +Error Gralloc0Allocator::allocateOne(const IMapper::BufferDescriptorInfo& info, + buffer_handle_t* outBuffer, + uint32_t* outStride) { + if (info.layerCount > 1 || (info.usage >> 32) != 0) { + return Error::BAD_VALUE; + } + + buffer_handle_t buffer = nullptr; + int stride = 0; + int result = mDevice->alloc(mDevice, info.width, info.height, + static_cast(info.format), info.usage, + &buffer, &stride); + if (result) { + switch (result) { + case -EINVAL: + return Error::BAD_VALUE; + default: + return Error::NO_RESOURCES; + } + } + + *outBuffer = buffer; + *outStride = stride; + + return Error::NONE; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.h b/graphics/allocator/2.0/default/Gralloc0Allocator.h new file mode 100644 index 0000000000..0e90527f70 --- /dev/null +++ b/graphics/allocator/2.0/default/Gralloc0Allocator.h @@ -0,0 +1,59 @@ +/* + * Copyright 2016 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_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H +#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::mapper::V2_0::IMapper; +using android::hardware::graphics::mapper::V2_0::BufferDescriptor; +using android::hardware::graphics::mapper::V2_0::Error; + +class Gralloc0Allocator : public IAllocator { + public: + Gralloc0Allocator(const hw_module_t* module); + virtual ~Gralloc0Allocator(); + + // IAllocator interface + Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; + Return allocate(const BufferDescriptor& descriptor, uint32_t count, + allocate_cb hidl_cb) override; + + private: + Error allocateOne(const IMapper::BufferDescriptorInfo& info, + buffer_handle_t* outBuffer, uint32_t* outStride); + + alloc_device_t* mDevice; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp new file mode 100644 index 0000000000..c0a5e1e0cb --- /dev/null +++ b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp @@ -0,0 +1,321 @@ +/* + * Copyright 2016 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 "Gralloc1Allocator" + +#include "Gralloc1Allocator.h" +#include "GrallocBufferDescriptor.h" + +#include + +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::common::V1_0::BufferUsage; +using android::hardware::graphics::mapper::V2_0::implementation:: + grallocDecodeBufferDescriptor; + +Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module) + : mDevice(nullptr), mCapabilities(), mDispatch() { + int result = gralloc1_open(module, &mDevice); + if (result) { + LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s", + strerror(-result)); + } + + initCapabilities(); + initDispatch(); +} + +Gralloc1Allocator::~Gralloc1Allocator() { + gralloc1_close(mDevice); +} + +void Gralloc1Allocator::initCapabilities() { + uint32_t count = 0; + mDevice->getCapabilities(mDevice, &count, nullptr); + + std::vector capabilities(count); + mDevice->getCapabilities(mDevice, &count, capabilities.data()); + capabilities.resize(count); + + for (auto capability : capabilities) { + if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) { + mCapabilities.layeredBuffers = true; + break; + } + } +} + +template +void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc, + T* outPfn) { + auto pfn = mDevice->getFunction(mDevice, desc); + if (!pfn) { + LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc); + } + + *outPfn = reinterpret_cast(pfn); +} + +void Gralloc1Allocator::initDispatch() { + initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump); + initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, + &mDispatch.createDescriptor); + initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, + &mDispatch.destroyDescriptor); + initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions); + initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat); + if (mCapabilities.layeredBuffers) { + initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT, + &mDispatch.setLayerCount); + } + initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, + &mDispatch.setConsumerUsage); + initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, + &mDispatch.setProducerUsage); + initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride); + initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate); + initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release); +} + +Return Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) { + uint32_t len = 0; + mDispatch.dump(mDevice, &len, nullptr); + + std::vector buf(len + 1); + mDispatch.dump(mDevice, &len, buf.data()); + buf.resize(len + 1); + buf[len] = '\0'; + + hidl_string reply; + reply.setToExternal(buf.data(), len); + hidl_cb(reply); + + return Void(); +} + +Return Gralloc1Allocator::allocate(const BufferDescriptor& descriptor, + uint32_t count, allocate_cb hidl_cb) { + IMapper::BufferDescriptorInfo descriptorInfo; + if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) { + hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec()); + return Void(); + } + + gralloc1_buffer_descriptor_t desc; + Error error = createDescriptor(descriptorInfo, &desc); + if (error != Error::NONE) { + hidl_cb(error, 0, hidl_vec()); + return Void(); + } + + uint32_t stride = 0; + std::vector buffers; + buffers.reserve(count); + + // allocate the buffers + for (uint32_t i = 0; i < count; i++) { + buffer_handle_t tmpBuffer; + uint32_t tmpStride; + error = allocateOne(desc, &tmpBuffer, &tmpStride); + if (error != Error::NONE) { + break; + } + + if (stride == 0) { + stride = tmpStride; + } else if (stride != tmpStride) { + // non-uniform strides + mDispatch.release(mDevice, tmpBuffer); + stride = 0; + error = Error::UNSUPPORTED; + break; + } + + buffers.emplace_back(hidl_handle(tmpBuffer)); + } + + mDispatch.destroyDescriptor(mDevice, desc); + + // return the buffers + hidl_vec hidl_buffers; + if (error == Error::NONE) { + hidl_buffers.setToExternal(buffers.data(), buffers.size()); + } + hidl_cb(error, stride, hidl_buffers); + + // free the buffers + for (const auto& buffer : buffers) { + mDispatch.release(mDevice, buffer.getNativeHandle()); + } + + return Void(); +} + +Error Gralloc1Allocator::toError(int32_t error) { + switch (error) { + case GRALLOC1_ERROR_NONE: + return Error::NONE; + case GRALLOC1_ERROR_BAD_DESCRIPTOR: + return Error::BAD_DESCRIPTOR; + case GRALLOC1_ERROR_BAD_HANDLE: + return Error::BAD_BUFFER; + case GRALLOC1_ERROR_BAD_VALUE: + return Error::BAD_VALUE; + case GRALLOC1_ERROR_NOT_SHARED: + return Error::NONE; // this is fine + case GRALLOC1_ERROR_NO_RESOURCES: + return Error::NO_RESOURCES; + case GRALLOC1_ERROR_UNDEFINED: + case GRALLOC1_ERROR_UNSUPPORTED: + default: + return Error::UNSUPPORTED; + } +} + +uint64_t Gralloc1Allocator::toProducerUsage(uint64_t usage) { + // this is potentially broken as we have no idea which private flags + // should be filtered out + uint64_t producerUsage = + usage & + ~static_cast(BufferUsage::CPU_READ_MASK | + BufferUsage::CPU_WRITE_MASK); + + switch (usage & BufferUsage::CPU_WRITE_MASK) { + case static_cast(BufferUsage::CPU_WRITE_RARELY): + producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE; + break; + case static_cast(BufferUsage::CPU_WRITE_OFTEN): + producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN; + break; + default: + break; + } + + switch (usage & BufferUsage::CPU_READ_MASK) { + case static_cast(BufferUsage::CPU_READ_RARELY): + producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ; + break; + case static_cast(BufferUsage::CPU_READ_OFTEN): + producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN; + break; + default: + break; + } + + return producerUsage; +} + +uint64_t Gralloc1Allocator::toConsumerUsage(uint64_t usage) { + // this is potentially broken as we have no idea which private flags + // should be filtered out + uint64_t consumerUsage = + usage & + ~static_cast(BufferUsage::CPU_READ_MASK | + BufferUsage::CPU_WRITE_MASK); + + switch (usage & BufferUsage::CPU_READ_MASK) { + case static_cast(BufferUsage::CPU_READ_RARELY): + consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ; + break; + case static_cast(BufferUsage::CPU_READ_OFTEN): + consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN; + break; + default: + break; + } + + return consumerUsage; +} + +Error Gralloc1Allocator::createDescriptor( + const IMapper::BufferDescriptorInfo& info, + gralloc1_buffer_descriptor_t* outDescriptor) { + gralloc1_buffer_descriptor_t descriptor; + + int32_t error = mDispatch.createDescriptor(mDevice, &descriptor); + + if (error == GRALLOC1_ERROR_NONE) { + error = mDispatch.setDimensions(mDevice, descriptor, info.width, + info.height); + } + if (error == GRALLOC1_ERROR_NONE) { + error = mDispatch.setFormat(mDevice, descriptor, + static_cast(info.format)); + } + if (error == GRALLOC1_ERROR_NONE) { + if (mCapabilities.layeredBuffers) { + error = + mDispatch.setLayerCount(mDevice, descriptor, info.layerCount); + } else if (info.layerCount > 1) { + error = GRALLOC1_ERROR_UNSUPPORTED; + } + } + if (error == GRALLOC1_ERROR_NONE) { + error = mDispatch.setProducerUsage(mDevice, descriptor, + toProducerUsage(info.usage)); + } + if (error == GRALLOC1_ERROR_NONE) { + error = mDispatch.setConsumerUsage(mDevice, descriptor, + toConsumerUsage(info.usage)); + } + + if (error == GRALLOC1_ERROR_NONE) { + *outDescriptor = descriptor; + } else { + mDispatch.destroyDescriptor(mDevice, descriptor); + } + + return toError(error); +} + +Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor, + buffer_handle_t* outBuffer, + uint32_t* outStride) { + buffer_handle_t buffer = nullptr; + int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer); + if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) { + return toError(error); + } + + uint32_t stride = 0; + error = mDispatch.getStride(mDevice, buffer, &stride); + if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) { + mDispatch.release(mDevice, buffer); + return toError(error); + } + + *outBuffer = buffer; + *outStride = stride; + + return Error::NONE; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.h b/graphics/allocator/2.0/default/Gralloc1Allocator.h new file mode 100644 index 0000000000..7b5a96613f --- /dev/null +++ b/graphics/allocator/2.0/default/Gralloc1Allocator.h @@ -0,0 +1,89 @@ +/* + * Copyright 2016 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_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H +#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::mapper::V2_0::IMapper; +using android::hardware::graphics::mapper::V2_0::BufferDescriptor; +using android::hardware::graphics::mapper::V2_0::Error; + +class Gralloc1Allocator : public IAllocator { + public: + Gralloc1Allocator(const hw_module_t* module); + virtual ~Gralloc1Allocator(); + + // IAllocator interface + Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; + Return allocate(const BufferDescriptor& descriptor, uint32_t count, + allocate_cb hidl_cb) override; + + private: + void initCapabilities(); + + template + void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn); + void initDispatch(); + + static Error toError(int32_t error); + static uint64_t toProducerUsage(uint64_t usage); + static uint64_t toConsumerUsage(uint64_t usage); + + Error createDescriptor(const IMapper::BufferDescriptorInfo& info, + gralloc1_buffer_descriptor_t* outDescriptor); + Error allocateOne(gralloc1_buffer_descriptor_t descriptor, + buffer_handle_t* outBuffer, uint32_t* outStride); + + gralloc1_device_t* mDevice; + + struct { + bool layeredBuffers; + } mCapabilities; + + struct { + GRALLOC1_PFN_DUMP dump; + GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor; + GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor; + GRALLOC1_PFN_SET_DIMENSIONS setDimensions; + GRALLOC1_PFN_SET_FORMAT setFormat; + GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount; + GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage; + GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage; + GRALLOC1_PFN_GET_STRIDE getStride; + GRALLOC1_PFN_ALLOCATE allocate; + GRALLOC1_PFN_RELEASE release; + } mDispatch; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H diff --git a/graphics/allocator/2.0/types.hal b/graphics/allocator/2.0/types.hal deleted file mode 100644 index d9b184bba3..0000000000 --- a/graphics/allocator/2.0/types.hal +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -package android.hardware.graphics.allocator@2.0; - -enum Error : int32_t { - NONE = 0, /** no error */ - BAD_DESCRIPTOR = 1, /** invalid BufferDescriptor */ - BAD_BUFFER = 2, /** invalid Buffer */ - BAD_VALUE = 3, /** invalid width, height, etc. */ - NOT_SHARED = 4, /** buffers not sharing backing store */ - NO_RESOURCES = 5, /** temporary failure due to resource contention */ - UNDEFINED = 6, /** an operation has no defined meaning */ - UNSUPPORTED = 7, /** permanent failure */ -}; - -enum ProducerUsage : uint64_t { - /** bit 0 is reserved */ - - /** buffer is read by CPU occasionally */ - CPU_READ = 1ULL << 1, - /** buffer is read by CPU frequently */ - CPU_READ_OFTEN = 1ULL << 2, - - /** bit 3 is reserved */ - /** bit 4 is reserved */ - - /** buffer is written by CPU occasionally */ - CPU_WRITE = 1ULL << 5, - /** buffer is written by CPU frequently */ - CPU_WRITE_OFTEN = 1ULL << 6, - - /** bit 7 is reserved */ - /** bit 8 is reserved */ - - /** buffer is used as a GPU render target */ - GPU_RENDER_TARGET = 1ULL << 9, - - /** bit 10 is reserved */ - /** bit 11 is reserved */ - /** bit 12 is reserved */ - /** bit 13 is reserved */ - - /** - * Buffer is allocated with hardware-level protection against copying the - * contents (or information derived from the contents) into unprotected - * memory. - */ - PROTECTED = 1ULL << 14, - - /** bit 15 is reserved */ - /** bit 16 is reserved */ - - /** buffer is used as a camera HAL output */ - CAMERA = 1ULL << 17, - - /** bit 18 is reserved */ - /** bit 19 is reserved */ - /** bit 20 is reserved */ - /** bit 21 is reserved */ - - /** buffer is used as a video decoder output */ - VIDEO_DECODER = 1ULL << 22, - - /** buffer is used as a sensor direct report output */ - SENSOR_DIRECT_DATA = 1ULL << 23, - - /** bits 24-27 are reserved for future versions */ - /** bits 28-31 are reserved for vendor extensions */ - - /** bits 32-47 are reserved for future versions */ - /** bits 48-63 are reserved for vendor extensions */ -}; - -enum ConsumerUsage : uint64_t { - /** bit 0 is reserved */ - - /** buffer is read by CPU occasionally */ - CPU_READ = 1ULL << 1, - /** buffer is read by CPU frequently */ - CPU_READ_OFTEN = 1ULL << 2, - - /** bit 3 is reserved */ - /** bit 4 is reserved */ - /** bit 5 is reserved */ - /** bit 6 is reserved */ - /** bit 7 is reserved */ - - /** buffer is used as a GPU texture */ - GPU_TEXTURE = 1ULL << 8, - - /** bit 9 is reserved */ - /** bit 10 is reserved */ - - /** buffer is used by hwcomposer HAL */ - HWCOMPOSER = 1ULL << 11, - /** buffer is a hwcomposer HAL client target */ - CLIENT_TARGET = 1ULL << 12, - - /** bit 13 is reserved */ - /** bit 14 is reserved */ - - /** buffer is used as a hwcomposer HAL cursor */ - CURSOR = 1ULL << 15, - - /** buffer is used as a video encoder input */ - VIDEO_ENCODER = 1ULL << 16, - - /** bit 17 is reserved */ - - /** buffer is used as a camera HAL input */ - CAMERA = 1ULL << 18, - - /** bit 19 is reserved */ - - /** buffer is used as a renderscript allocation */ - RENDERSCRIPT = 1ULL << 20, - - /** bit 21 is reserved */ - /** bit 22 is reserved */ - - /** - * buffer is used as as an OpenGL shader storage or uniform - buffer object */ - GPU_DATA_BUFFER = 1ULL << 23, - - /** bits 24-27 are reserved for future versions */ - /** bits 28-31 are reserved for vendor extensions */ - - /** bits 32-47 are reserved for future versions */ - /** bits 48-63 are reserved for vendor extensions */ -}; - -typedef uint64_t BufferDescriptor; -typedef uint64_t Buffer; diff --git a/graphics/allocator/2.0/vts/functional/Android.bp b/graphics/allocator/2.0/vts/functional/Android.bp deleted file mode 100644 index fb77ab322a..0000000000 --- a/graphics/allocator/2.0/vts/functional/Android.bp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (C) 2016 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. -// - -cc_library_static { - name: "libVtsHalGraphicsAllocatorTestUtils", - defaults: ["hidl_defaults"], - srcs: ["VtsHalGraphicsAllocatorTestUtils.cpp"], - shared_libs: [ - "android.hardware.graphics.allocator@2.0", - ], - static_libs: [ - "VtsHalHidlTargetTestBase", - ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-O0", - "-g", - ], - export_include_dirs: ["."], -} - -cc_test { - name: "VtsHalGraphicsAllocatorV2_0TargetTest", - defaults: ["hidl_defaults"], - srcs: ["VtsHalGraphicsAllocatorV2_0TargetTest.cpp"], - shared_libs: [ - "libbase", - "liblog", - "libcutils", - "libhidlbase", - "libhidltransport", - "libnativehelper", - "libutils", - "android.hardware.graphics.allocator@2.0", - ], - static_libs: [ - "libVtsHalGraphicsAllocatorTestUtils", - "VtsHalHidlTargetTestBase", - ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-O0", - "-g", - ] -} diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp deleted file mode 100644 index 0dc43be640..0000000000 --- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2017 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 "VtsHalGraphicsAllocatorTestUtils.h" - -namespace android { -namespace hardware { -namespace graphics { -namespace allocator { -namespace V2_0 { -namespace tests { - -Allocator::Allocator() { init(); } - -void Allocator::init() { - mAllocator = ::testing::VtsHalHidlTargetTestBase::getService(); - ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service"; - - std::vector capabilities = getCapabilities(); - mCapabilities.insert(capabilities.begin(), capabilities.end()); -} - -sp Allocator::getRaw() const { return mAllocator; } - -bool Allocator::hasCapability(IAllocator::Capability capability) const { - return mCapabilities.count(capability) > 0; -} - -std::vector Allocator::getCapabilities() { - std::vector capabilities; - mAllocator->getCapabilities( - [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; }); - - return capabilities; -} - -std::string Allocator::dumpDebugInfo() { - std::string debugInfo; - mAllocator->dumpDebugInfo( - [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); - - return debugInfo; -} - -std::unique_ptr Allocator::createClient() { - std::unique_ptr client; - mAllocator->createClient([&](const auto& tmpError, const auto& tmpClient) { - ASSERT_EQ(Error::NONE, tmpError) << "failed to create client"; - client = std::make_unique(tmpClient); - }); - - return client; -} - -AllocatorClient::AllocatorClient(const sp& client) - : mClient(client) {} - -AllocatorClient::~AllocatorClient() { - for (auto buffer : mBuffers) { - EXPECT_EQ(Error::NONE, mClient->free(buffer)) - << "failed to free buffer " << buffer; - } - mBuffers.clear(); - - for (auto descriptor : mDescriptors) { - EXPECT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor)) - << "failed to destroy descriptor " << descriptor; - } - mDescriptors.clear(); -} - -sp AllocatorClient::getRaw() const { return mClient; } - -BufferDescriptor AllocatorClient::createDescriptor( - const IAllocatorClient::BufferDescriptorInfo& info) { - BufferDescriptor descriptor = 0; - mClient->createDescriptor( - info, [&](const auto& tmpError, const auto& tmpDescriptor) { - ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor"; - descriptor = tmpDescriptor; - - EXPECT_TRUE(mDescriptors.insert(descriptor).second) - << "duplicated descriptor id " << descriptor; - }); - - return descriptor; -} - -void AllocatorClient::destroyDescriptor(BufferDescriptor descriptor) { - ASSERT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor)) - << "failed to destroy descriptor " << descriptor; - - mDescriptors.erase(descriptor); -} - -Error AllocatorClient::testAllocate( - const std::vector& descriptors) { - return mClient->testAllocate(descriptors); -} - -bool AllocatorClient::testAllocate(BufferDescriptor descriptor) { - std::vector descriptors(1, descriptor); - Error error = testAllocate(descriptors); - return (error == Error::NONE || error == Error::NOT_SHARED); -} - -Error AllocatorClient::allocate( - const std::vector& descriptors, - std::vector& buffers) { - Error error = Error::NO_RESOURCES; - mClient->allocate(descriptors, [&](const auto& tmpError, - const auto& tmpBuffers) { - ASSERT_TRUE(tmpError == Error::NONE || tmpError == Error::NOT_SHARED) - << "failed to allocate buffer"; - ASSERT_EQ(descriptors.size(), tmpBuffers.size()) << "invalid buffer count"; - - error = tmpError; - buffers = tmpBuffers; - - for (auto buffer : buffers) { - EXPECT_TRUE(mBuffers.insert(buffer).second) - << "duplicated buffer id " << buffer; - } - }); - - return error; -} - -Buffer AllocatorClient::allocate(BufferDescriptor descriptor) { - std::vector descriptors(1, descriptor); - std::vector buffers; - allocate(descriptors, buffers); - if (::testing::Test::HasFatalFailure()) { - return 0; - } - - return buffers[0]; -} - -void AllocatorClient::free(Buffer buffer) { - ASSERT_EQ(Error::NONE, mClient->free(buffer)) - << "failed to free buffer " << buffer; - - mBuffers.erase(buffer); -} - -native_handle_t* AllocatorClient::exportHandle(BufferDescriptor descriptor, - Buffer buffer) { - native_handle_t* handle; - mClient->exportHandle( - descriptor, buffer, [&](const auto& tmpError, const auto& tmpHandle) { - ASSERT_EQ(Error::NONE, tmpError) << "failed to export buffer handle"; - ASSERT_NE(nullptr, tmpHandle.getNativeHandle()) - << "invalid buffer handle"; - - handle = native_handle_clone(tmpHandle.getNativeHandle()); - ASSERT_NE(nullptr, handle) << "failed to clone handle"; - }); - - return handle; -} - -} // namespace tests -} // namespace V2_0 -} // namespace allocator -} // namespace graphics -} // namespace hardware -} // namespace android diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h deleted file mode 100644 index c9bfe8fd82..0000000000 --- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2017 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 VTS_HAL_GRAPHICS_ALLOCATOR_UTILS -#define VTS_HAL_GRAPHICS_ALLOCATOR_UTILS - -#include -#include -#include -#include - -#include -#include - -namespace android { -namespace hardware { -namespace graphics { -namespace allocator { -namespace V2_0 { -namespace tests { - -class AllocatorClient; - -// A wrapper to IAllocator. -class Allocator { - public: - Allocator(); - - sp getRaw() const; - - // Returns true when the allocator supports the specified capability. - bool hasCapability(IAllocator::Capability capability) const; - - std::vector getCapabilities(); - std::string dumpDebugInfo(); - std::unique_ptr createClient(); - - private: - void init(); - - sp mAllocator; - std::unordered_set mCapabilities; -}; - -// A wrapper to IAllocatorClient. -class AllocatorClient { - public: - AllocatorClient(const sp& client); - ~AllocatorClient(); - - sp getRaw() const; - - BufferDescriptor createDescriptor( - const IAllocatorClient::BufferDescriptorInfo& info); - void destroyDescriptor(BufferDescriptor descriptor); - - Error testAllocate(const std::vector& descriptors); - bool testAllocate(BufferDescriptor descriptor); - - Error allocate(const std::vector& descriptors, - std::vector& buffers); - Buffer allocate(BufferDescriptor descriptor); - void free(Buffer buffer); - - // Returns a handle to the buffer. The ownership of the handle is - // transferred to the caller. - native_handle_t* exportHandle(BufferDescriptor descriptor, Buffer buffer); - - private: - sp mClient; - - // Keep track of all descriptors and buffers. When a test fails with - // ASSERT_*, the destructor will clean up the resources for the test. - std::unordered_set mDescriptors; - std::unordered_set mBuffers; -}; - -} // namespace tests -} // namespace V2_0 -} // namespace allocator -} // namespace graphics -} // namespace hardware -} // namespace android - -#endif // VTS_HAL_GRAPHICS_ALLOCATOR_UTILS diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp deleted file mode 100644 index b1c764fc90..0000000000 --- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2016 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 "graphics_allocator_hidl_hal_test" - -#include -#include - -#include "VtsHalGraphicsAllocatorTestUtils.h" - -namespace android { -namespace hardware { -namespace graphics { -namespace allocator { -namespace V2_0 { -namespace tests { -namespace { - -using android::hardware::graphics::common::V1_0::PixelFormat; - -#define CHECK_FEATURE_OR_SKIP(FEATURE_NAME) \ - do { \ - if (!mAllocator->hasCapability(FEATURE_NAME)) { \ - std::cout << "[ SKIPPED ] Feature " << #FEATURE_NAME \ - << " not supported" << std::endl; \ - return; \ - } \ - } while (0) - -class GraphicsAllocatorHidlTest : public ::testing::VtsHalHidlTargetTestBase { - protected: - void SetUp() override { - ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique()); - ASSERT_NO_FATAL_FAILURE(mClient = mAllocator->createClient()); - - mDummyDescriptorInfo.width = 64; - mDummyDescriptorInfo.height = 64; - mDummyDescriptorInfo.layerCount = 1; - mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; - mDummyDescriptorInfo.producerUsageMask = - static_cast(ProducerUsage::CPU_WRITE); - mDummyDescriptorInfo.consumerUsageMask = - static_cast(ConsumerUsage::CPU_READ); - } - - void TearDown() override {} - - std::unique_ptr mAllocator; - std::unique_ptr mClient; - IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{}; -}; - -TEST_F(GraphicsAllocatorHidlTest, GetCapabilities) { - auto capabilities = mAllocator->getCapabilities(); - for (auto cap : capabilities) { - EXPECT_NE(IAllocator::Capability::INVALID, cap); - } -} - -TEST_F(GraphicsAllocatorHidlTest, DumpDebugInfo) { - mAllocator->dumpDebugInfo(); -} - -TEST_F(GraphicsAllocatorHidlTest, CreateDestroyDescriptor) { - BufferDescriptor descriptor; - ASSERT_NO_FATAL_FAILURE(descriptor = - mClient->createDescriptor(mDummyDescriptorInfo)); - mClient->destroyDescriptor(descriptor); -} - -/** - * Test testAllocate with a single buffer descriptor. - */ -TEST_F(GraphicsAllocatorHidlTest, TestAllocateBasic) { - CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE); - - BufferDescriptor descriptor; - ASSERT_NO_FATAL_FAILURE(descriptor = - mClient->createDescriptor(mDummyDescriptorInfo)); - - ASSERT_TRUE(mClient->testAllocate(descriptor)); -} - -/** - * Test testAllocate with two buffer descriptors. - */ -TEST_F(GraphicsAllocatorHidlTest, TestAllocateArray) { - CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE); - - BufferDescriptor descriptor; - ASSERT_NO_FATAL_FAILURE(descriptor = - mClient->createDescriptor(mDummyDescriptorInfo)); - - hidl_vec descriptors; - descriptors.resize(2); - descriptors[0] = descriptor; - descriptors[1] = descriptor; - - auto error = mClient->testAllocate(descriptors); - ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED); -} - -/** - * Test allocate/free with a single buffer descriptor. - */ -TEST_F(GraphicsAllocatorHidlTest, AllocateFreeBasic) { - BufferDescriptor descriptor; - ASSERT_NO_FATAL_FAILURE(descriptor = - mClient->createDescriptor(mDummyDescriptorInfo)); - - Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor)); - - mClient->free(buffer); -} - -/** - * Test allocate/free with an array of buffer descriptors. - */ -TEST_F(GraphicsAllocatorHidlTest, AllocateFreeArray) { - BufferDescriptor descriptor1; - ASSERT_NO_FATAL_FAILURE(descriptor1 = - mClient->createDescriptor(mDummyDescriptorInfo)); - - BufferDescriptor descriptor2; - ASSERT_NO_FATAL_FAILURE(descriptor2 = - mClient->createDescriptor(mDummyDescriptorInfo)); - - hidl_vec descriptors; - descriptors.resize(3); - descriptors[0] = descriptor1; - descriptors[1] = descriptor1; - descriptors[2] = descriptor2; - - std::vector buffers; - ASSERT_NO_FATAL_FAILURE(mClient->allocate(descriptors, buffers)); - - for (auto buf : buffers) { - mClient->free(buf); - } -} - -TEST_F(GraphicsAllocatorHidlTest, ExportHandle) { - BufferDescriptor descriptor; - ASSERT_NO_FATAL_FAILURE(descriptor = - mClient->createDescriptor(mDummyDescriptorInfo)); - - Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor)); - - native_handle_t* handle; - ASSERT_NO_FATAL_FAILURE(handle = mClient->exportHandle(descriptor, buffer)); - - native_handle_close(handle); - native_handle_delete(handle); -} - -} // namespace anonymous -} // namespace tests -} // namespace V2_0 -} // namespace allocator -} // namespace graphics -} // namespace hardware -} // namespace android - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - - int status = RUN_ALL_TESTS(); - LOG(INFO) << "Test result = " << status; - - return status; -} diff --git a/graphics/common/1.0/Android.mk b/graphics/common/1.0/Android.mk index c08053de4d..ae80c6afd9 100644 --- a/graphics/common/1.0/Android.mk +++ b/graphics/common/1.0/Android.mk @@ -12,6 +12,25 @@ intermediates := $(call local-generated-sources-dir, COMMON) HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX) +# +# Build types.hal (BufferUsage) +# +GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java +$(GEN): $(HIDL) +$(GEN): PRIVATE_HIDL := $(HIDL) +$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal +$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates) +$(GEN): PRIVATE_CUSTOM_TOOL = \ + $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \ + -Ljava \ + -randroid.hardware:hardware/interfaces \ + -randroid.hidl:system/libhidl/transport \ + android.hardware.graphics.common@1.0::types.BufferUsage + +$(GEN): $(LOCAL_PATH)/types.hal + $(transform-generated-source) +LOCAL_GENERATED_SOURCES += $(GEN) + # # Build types.hal (ColorMode) # @@ -138,6 +157,25 @@ intermediates := $(call local-generated-sources-dir, COMMON) HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX) +# +# Build types.hal (BufferUsage) +# +GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java +$(GEN): $(HIDL) +$(GEN): PRIVATE_HIDL := $(HIDL) +$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal +$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates) +$(GEN): PRIVATE_CUSTOM_TOOL = \ + $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \ + -Ljava \ + -randroid.hardware:hardware/interfaces \ + -randroid.hidl:system/libhidl/transport \ + android.hardware.graphics.common@1.0::types.BufferUsage + +$(GEN): $(LOCAL_PATH)/types.hal + $(transform-generated-source) +LOCAL_GENERATED_SOURCES += $(GEN) + # # Build types.hal (ColorMode) # diff --git a/graphics/common/1.0/types.hal b/graphics/common/1.0/types.hal index 979e4c422e..6d94d76a75 100644 --- a/graphics/common/1.0/types.hal +++ b/graphics/common/1.0/types.hal @@ -441,6 +441,90 @@ enum PixelFormat : int32_t { JPEG = 0x100, }; +/** + * Buffer usage definitions. + */ +enum BufferUsage : uint64_t { + /** bit 0-3 is an enum */ + CPU_READ_MASK = 0xfULL, + /** buffer is never read by CPU */ + CPU_READ_NEVER = 0, + /** buffer is rarely read by CPU */ + CPU_READ_RARELY = 2, + /** buffer is often read by CPU */ + CPU_READ_OFTEN = 3, + + /** bit 4-7 is an enum */ + CPU_WRITE_MASK = 0xfULL << 4, + /** buffer is never written by CPU */ + CPU_WRITE_NEVER = 0 << 4, + /** buffer is rarely written by CPU */ + CPU_WRITE_RARELY = 2 << 4, + /** buffer is often written by CPU */ + CPU_WRITE_OFTEN = 3 << 4, + + /** buffer is used as a GPU texture */ + GPU_TEXTURE = 1ULL << 8, + + /** buffer is used as a GPU render target */ + GPU_RENDER_TARGET = 1ULL << 9, + + /** bit 10 must be zero */ + + /** buffer is used as a composer HAL overlay layer */ + COMPOSER_OVERLAY = 1ULL << 11, + /** buffer is used as a composer HAL client target */ + COMPOSER_CLIENT_TARGET = 1ULL << 12, + + /** bit 13 must be zero */ + + /** + * Buffer is allocated with hardware-level protection against copying the + * contents (or information derived from the contents) into unprotected + * memory. + */ + PROTECTED = 1ULL << 14, + + /** buffer is used as a hwcomposer HAL cursor layer */ + COMPOSER_CURSOR = 1ULL << 15, + + /** buffer is used as a video encoder input */ + VIDEO_ENCODER = 1ULL << 16, + + /** buffer is used as a camera HAL output */ + CAMERA_OUTPUT = 1ULL << 17, + + /** buffer is used as a camera HAL input */ + CAMERA_INPUT = 1ULL << 18, + + /** bit 19 must be zero */ + + /** buffer is used as a renderscript allocation */ + RENDERSCRIPT = 1ULL << 20, + + /** bit 21 must be zero */ + + /** buffer is used as a video decoder output */ + VIDEO_DECODER = 1ULL << 22, + + /** buffer is used as a sensor direct report output */ + SENSOR_DIRECT_DATA = 1ULL << 23, + + /** + * buffer is used as as an OpenGL shader storage or uniform + * buffer object + */ + GPU_DATA_BUFFER = 1ULL << 24, + + /** bits 25-27 must be zero and are reserved for future versions */ + /** bits 28-31 are reserved for vendor extensions */ + VENDOR_MASK = 0xfULL << 28, + + /** bits 32-47 must be zero and are reserved for future versions */ + /** bits 48-63 are reserved for vendor extensions */ + VENDOR_MASK_HI = 0xffffULL << 48, +}; + /** * Transformation definitions * diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp index 8e1f925c17..66323d4a4f 100644 --- a/graphics/composer/2.1/vts/functional/Android.bp +++ b/graphics/composer/2.1/vts/functional/Android.bp @@ -52,7 +52,6 @@ cc_test { ], static_libs: [ "libhwcomposer-command-buffer", - "libVtsHalGraphicsAllocatorTestUtils", "libVtsHalGraphicsComposerTestUtils", "libVtsHalGraphicsMapperTestUtils", "VtsHalHidlTargetTestBase", diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 0da3a33194..387222fbbe 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -18,7 +18,6 @@ #include #include -#include "VtsHalGraphicsAllocatorTestUtils.h" #include "VtsHalGraphicsComposerTestUtils.h" #include "VtsHalGraphicsMapperTestUtils.h" @@ -40,22 +39,15 @@ namespace V2_1 { namespace tests { namespace { -using android::hardware::graphics::allocator::V2_0::Buffer; -using android::hardware::graphics::allocator::V2_0::BufferDescriptor; -using android::hardware::graphics::allocator::V2_0::ConsumerUsage; -using android::hardware::graphics::allocator::V2_0::IAllocator; -using android::hardware::graphics::allocator::V2_0::IAllocatorClient; -using android::hardware::graphics::allocator::V2_0::ProducerUsage; -using android::hardware::graphics::allocator::V2_0::tests::Allocator; -using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient; +using android::hardware::graphics::common::V1_0::BufferUsage; using android::hardware::graphics::common::V1_0::ColorMode; using android::hardware::graphics::common::V1_0::ColorTransform; using android::hardware::graphics::common::V1_0::Dataspace; using android::hardware::graphics::common::V1_0::PixelFormat; using android::hardware::graphics::common::V1_0::Transform; using android::hardware::graphics::mapper::V2_0::IMapper; -using android::hardware::graphics::mapper::V2_0::tests::Mapper; -using GrallocError = android::hardware::graphics::allocator::V2_0::Error; +using android::hardware::graphics::mapper::V2_0::tests::Gralloc; +using GrallocError = android::hardware::graphics::mapper::V2_0::Error; // IComposerCallback to be installed with IComposerClient::registerCallback. class GraphicsComposerCallback : public IComposerCallback { @@ -409,9 +401,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { void SetUp() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp()); - ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique()); - ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient()); - ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique()); + ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique()); mWriter = std::make_unique(1024); mReader = std::make_unique(); @@ -422,15 +412,15 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { } const native_handle_t* allocate() { - IAllocatorClient::BufferDescriptorInfo info{}; - info.width = 64; - info.height = 64; - info.layerCount = 1; - info.format = PixelFormat::RGBA_8888; - info.producerUsageMask = static_cast(ProducerUsage::CPU_WRITE); - info.consumerUsageMask = static_cast(ConsumerUsage::CPU_READ); + IMapper::BufferDescriptorInfo info{}; + info.width = 64; + info.height = 64; + info.layerCount = 1; + info.format = PixelFormat::RGBA_8888; + info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::CPU_READ_OFTEN); - return mMapper->allocate(mAllocatorClient, info); + return mGralloc->allocate(info); } void execute() { @@ -507,9 +497,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { std::unique_ptr mReader; private: - std::unique_ptr mAllocator; - std::unique_ptr mAllocatorClient; - std::unique_ptr mMapper; + std::unique_ptr mGralloc; }; /** diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp index 98a509bb5a..cc2bd73c8f 100644 --- a/graphics/mapper/2.0/Android.bp +++ b/graphics/mapper/2.0/Android.bp @@ -51,7 +51,6 @@ cc_library_shared { "liblog", "libutils", "libcutils", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], @@ -60,7 +59,6 @@ cc_library_shared { "libhidltransport", "libhwbinder", "libutils", - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.common@1.0", "android.hidl.base@1.0", ], diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal index 573dcd09d0..246be240f2 100644 --- a/graphics/mapper/2.0/IMapper.hal +++ b/graphics/mapper/2.0/IMapper.hal @@ -16,10 +16,39 @@ package android.hardware.graphics.mapper@2.0; -import android.hardware.graphics.common@1.0::PixelFormat; -import android.hardware.graphics.allocator@2.0; +import android.hardware.graphics.common@1.0; interface IMapper { + struct BufferDescriptorInfo { + /** + * The width specifies how many columns of pixels must be in the + * allocated buffer, but does not necessarily represent the offset in + * columns between the same column in adjacent rows. The rows may be + * padded. + */ + uint32_t width; + + /** + * The height specifies how many rows of pixels must be in the + * allocated buffer. + */ + uint32_t height; + + /** + * The number of image layers that must be in the allocated buffer. + */ + uint32_t layerCount; + + /** Buffer pixel format. */ + PixelFormat format; + + /** + * Buffer usage mask; valid flags can be found in the definition of + * BufferUsage. + */ + bitfield usage; + }; + struct Rect { int32_t left; int32_t top; @@ -28,170 +57,76 @@ interface IMapper { }; /** - * Adds a reference to the given buffer handle. + * Creates a buffer descriptor. The descriptor can be used with IAllocator + * to allocate buffers. * - * A buffer handle received from a remote process or exported by - * IAllocator::exportHandle is unknown to the mapper. There is also no - * guarantee that the buffer's backing store will stay alive. This - * function must be called at least once in both cases to intrdouce the - * buffer handle to the mapper and to secure the backing store. It may - * also be called more than once to increase the reference count if two - * components in the same process want to interact with the buffer - * independently. + * Since the buffer descriptor fully describes a buffer, any device + * dependent or device independent checks must be performed here whenever + * possible. Specifically, when layered buffers are not supported, this + * function must return UNSUPPORTED if layerCount is great than 1. * - * @param bufferHandle is the buffer to which a reference must be added. + * @param descriptorInfo specifies the attributes of the descriptor. * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid - * NO_RESOURCES when it is not possible to add a - * reference to this buffer at this time + * BAD_VALUE when any of the specified attributes is + * invalid or conflicting. + * NO_RESOURCES when the creation cannot be fullfilled at + * this time. + * UNSUPPORTED when any of the specified attributes is + * not supported. + * @return descriptor is the newly created buffer descriptor. */ @entry @callflow(next="*") - retain(handle bufferHandle) generates (Error error); + createDescriptor(BufferDescriptorInfo descriptorInfo) + generates (Error error, + BufferDescriptor descriptor); /** - * Removes a reference from the given buffer buffer. + * Imports a raw buffer handle to create an imported buffer handle for use + * with the rest of the mapper or with other in-process libraries. * - * If no references remain, the buffer handle must be freed with - * native_handle_close/native_handle_delete by the mapper. When the last - * buffer handle referring to a particular backing store is freed, that - * backing store must also be freed. + * A buffer handle is considered raw when it is cloned or when it is + * received from another HAL or another process. A raw buffer handle must + * not be used to access the underlying graphics buffer. It must be + * imported to create an imported handle first. * - * @param bufferHandle is the buffer from which a reference must be - * removed. + * This function must at least validate the raw handle before creating the + * imported handle. It must also support importing the same raw handle + * multiple times to create multiple imported handles. The imported handle + * must be considered valid everywhere in the process, including in + * another instance of the mapper. + * + * @param rawHandle is the raw buffer handle to import. * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. + * BAD_BUFFER when the raw handle is invalid. + * NO_RESOURCES when the raw handle cannot be imported at + * this time. + * @return buffer is the imported buffer handle and has the type + * buffer_handle_t. + */ + @entry + @callflow(next="*") + importBuffer(handle rawHandle) generates (Error error, pointer buffer); + + /** + * Frees a buffer handle. Buffer handles returned by importBuffer must be + * freed with this function when no longer needed. + * + * This function must free up all resources allocated by importBuffer for + * the imported handle. For example, if the imported handle was created + * with native_handle_create, this function must call native_handle_close + * and native_handle_delete. + * + * @return error is NONE upon success. Otherwise, + * BAD_BUFFER when the buffer is invalid. */ @exit - release(handle bufferHandle) generates (Error error); - - /** - * Gets the width and height of the buffer in pixels. - * - * See IAllocator::BufferDescriptorInfo for more information. - * - * @param bufferHandle is the buffer from which to get the dimensions. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * @return width is the width of the buffer in pixels. - * @return height is the height of the buffer in pixels. - */ @callflow(next="*") - getDimensions(handle bufferHandle) - generates (Error error, - uint32_t width, - uint32_t height); - - /** - * Gets the format of the buffer. - * - * See IAllocator::BufferDescriptorInfo for more information. - * - * @param bufferHandle is the buffer from which to get format. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * @return format is the format of the buffer. - */ - @callflow(next="*") - getFormat(handle bufferHandle) - generates (Error error, - PixelFormat format); - - /** - * Gets the number of layers of the buffer. - * - * See IAllocator::BufferDescriptorInfo for more information. - * - * @param bufferHandle is the buffer from which to get format. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * @return layerCount is the number of layers of the buffer. - */ - @callflow(next="*") - getLayerCount(handle bufferHandle) - generates (Error error, - uint32_t layerCount); - - /** - * Gets the producer usage flags which were used to allocate this buffer. - * - * See IAllocator::BufferDescriptorInfo for more information. - * - * @param bufferHandle is the buffer from which to get the producer usage - * flags. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * @return usageMask contains the producer usage flags of the buffer. - */ - @callflow(next="*") - getProducerUsageMask(handle bufferHandle) - generates (Error error, - uint64_t usageMask); - - /** - * Gets the consumer usage flags which were used to allocate this buffer. - * - * See IAllocator::BufferDescriptorInfo for more information. - * - * @param bufferHandle is the buffer from which to get the consumer usage - * flags. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * @return usageMask contains the consumer usage flags of the buffer. - */ - @callflow(next="*") - getConsumerUsageMask(handle bufferHandle) - generates (Error error, - uint64_t usageMask); - - /** - * Gets a value that uniquely identifies the backing store of the given - * buffer. - * - * Buffers which share a backing store should return the same value from - * this function. If the buffer is present in more than one process, the - * backing store value for that buffer is not required to be the same in - * every process. - * - * @param device is the mapper device. - * @param bufferHandle is the buffer from which to get the backing store - * identifier. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * @return store is the backing store identifier for this buffer. - */ - @callflow(next="*") - getBackingStore(handle bufferHandle) - generates (Error error, - BackingStore store); - - /** - * Gets the stride of the buffer in pixels. - * - * The stride is the offset in pixel-sized elements between the same - * column in two adjacent rows of pixels. This may not be equal to the - * width of the buffer. - * - * @param device is the mapper device. - * @param bufferHandle is the buffer from which to get the stride. - * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * UNDEFINED when the notion of a stride is not - * meaningful for the buffer format. - * @return store is the stride in pixels. - */ - @callflow(next="*") - getStride(handle bufferHandle) - generates (Error error, - uint32_t stride); + freeBuffer(pointer buffer) generates (Error error); /** * Locks the given buffer for the specified CPU usage. * - * Exactly one of producerUsageMask and consumerUsageMask must be 0. The - * usage which is not 0 must be one of the *Usage::CPU* values, as - * applicable. Locking a buffer for a non-CPU usage is not supported. - * * Locking the same buffer simultaneously from multiple threads is * permitted, but if any of the threads attempt to lock the buffer for * writing, the behavior is undefined, except that it must not cause @@ -209,39 +144,27 @@ interface IMapper { * address will represent the top-left corner of the entire buffer, even * if accessRegion does not begin at the top-left corner. * - * acquireFence is a file descriptor referring to a acquire sync fence - * object, which will be signaled when it is safe for the device to access - * the contents of the buffer (prior to locking). If it is already safe to - * access the buffer contents, -1 may be passed instead. - * - * @param bufferHandle is the buffer to lock. - * @param producerUsageMask contains the producer usage flags to request; - * either this or consumerUsagemask must be 0, and the other must - * be a CPU usage. - * @param consumerUsageMask contains the consumer usage flags to request; - * either this or producerUsageMask must be 0, and the other must - * be a CPU usage. + * @param buffer is the buffer to lock. + * @param cpuUsage specifies one or more CPU usage flags to request. * @param accessRegion is the portion of the buffer that the client * intends to access. - * @param acquireFence is a sync fence file descriptor as described above. + * @param acquireFence, when non-empty, is a handle containing a file + * descriptor referring to a sync fence object, which will be + * signaled when it is safe for the mapper to lock the buffer. If + * it is already safe to lock, acquireFence is empty. * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * BAD_VALUE when neither or both of producerUsageMask - * and consumerUsageMask were 0, or the usage - * which was not 0 was not a CPU usage. + * BAD_BUFFER when the buffer is invalid or is + * incompatible with this function. + * BAD_VALUE when cpuUsage is 0, contains non-CPU usage + * flags, or is incompatible with the buffer. * NO_RESOURCES when the buffer cannot be locked at this * time, but locking may succeed at a future * time. - * UNSUPPORTED when the buffer cannot be locked with the - * given usage, and any future attempts at - * locking will also fail. - * @return data will be filled with a CPU-accessible pointer to the buffer - * data. + * @return data is a CPU-accessible pointer to the buffer data. */ @callflow(next="unlock") - lock(handle bufferHandle, - uint64_t producerUsageMask, - uint64_t consumerUsageMask, + lock(pointer buffer, + bitfield cpuUsage, Rect accessRegion, handle acquireFence) generates (Error error, @@ -249,7 +172,7 @@ interface IMapper { /** * This is largely the same as lock(), except that instead of returning a - * pointer directly to the buffer data, it returns an FlexLayout struct + * pointer directly to the buffer data, it returns an YCbCrLayout struct * describing how to access the data planes. * * This function must work on buffers with PixelFormat::YCbCr_*_888 if @@ -257,67 +180,46 @@ interface IMapper { * multimedia codecs when they are configured with a * flexible-YUV-compatible color format. * - * This function may also be called on buffers of other formats, including - * non-YUV formats, but if the buffer format is not compatible with a - * flexible representation, it may return UNSUPPORTED. - * - * @param device is the mapper device. - * @param bufferHandle is the buffer to lock. - * @param producerUsageMask contains the producer usage flags to request; - * either this or consumerUsagemask must be 0, and the other must - * be a CPU usage. - * @param consumerUsageMask contains the consumer usage flags to request; - * either this or producerUsageMask must be 0, and the other must - * be a CPU usage. + * @param buffer is the buffer to lock. + * @param cpuUsage specifies one or more CPU usage flags to request. * @param accessRegion is the portion of the buffer that the client * intends to access. - * @param acquireFence is a sync fence file descriptor as described in - * lock(). + * @param acquireFence, when non-empty, is a handle containing a file + * descriptor referring to a sync fence object, which will be + * signaled when it is safe for the mapper to lock the buffer. If + * it is already safe to lock, acquireFence is empty. * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * BAD_VALUE when neither or both of producerUsageMask - * and consumerUsageMask were 0, or the usage - * which was not 0 was not a CPU usage. + * BAD_BUFFER when the buffer is invalid or is + * incompatible with this function. + * BAD_VALUE when cpuUsage is 0, contains non-CPU usage + * flags, or is incompatible with the buffer. * NO_RESOURCES when the buffer cannot be locked at this * time, but locking may succeed at a future * time. - * UNSUPPORTED when the buffer cannot be locked with the - * given usage, and any future attempts at - * locking will also fail. - * @return flexLayout will be filled with the description of the planes in - * the buffer. + * @return layout is the data layout of the buffer. */ @callflow(next="unlock") - lockFlex(handle bufferHandle, - uint64_t producerUsageMask, - uint64_t consumerUsageMask, - Rect accessRegion, - handle acquireFence) + lockYCbCr(pointer buffer, + bitfield cpuUsage, + Rect accessRegion, + handle acquireFence) generates (Error error, - FlexLayout layout); + YCbCrLayout layout); /** - * This function indicates to the device that the client will be done with - * the buffer when releaseFence signals. + * Unlocks a buffer to indicate all CPU accesses to the buffer have + * completed. * - * releaseFence will be filled with a file descriptor referring to a - * release sync fence object, which will be signaled when it is safe to - * access the contents of the buffer (after the buffer has been unlocked). - * If it is already safe to access the buffer contents, then -1 may be - * returned instead. - * - * This function is used to unlock both buffers locked by lock() and those - * locked by lockFlex(). - * - * @param device is the mapper device. - * @param bufferHandle is the buffer to unlock. + * @param buffer is the buffer to unlock. * @return error is NONE upon success. Otherwise, - * BAD_BUFFER when the buffer handle is invalid. - * @return releaseFence is a sync fence file descriptor as described - * above. + * BAD_BUFFER when the buffer is invalid or not locked. + * @return releaseFence, when non-empty, is a handle containing a file + * descriptor referring to a sync fence object. The sync fence + * object will be signaled when the mapper has completed any + * pending work. */ @callflow(next="*") - unlock(handle bufferHandle) + unlock(pointer buffer) generates (Error error, handle releaseFence); }; diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp index 1dc5aea643..090c61fb39 100644 --- a/graphics/mapper/2.0/default/Android.bp +++ b/graphics/mapper/2.0/default/Android.bp @@ -18,10 +18,9 @@ cc_library_shared { defaults: ["hidl_defaults"], proprietary: true, relative_install_path: "hw", - srcs: ["GrallocMapper.cpp"], + srcs: ["GrallocMapper.cpp", "Gralloc0Mapper.cpp", "Gralloc1Mapper.cpp"], cppflags: ["-Wall", "-Wextra"], shared_libs: [ - "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.mapper@2.0", "libbase", "libcutils", @@ -29,6 +28,12 @@ cc_library_shared { "libhidlbase", "libhidltransport", "liblog", + "libsync", "libutils", ], } + +cc_library_static { + name: "libgrallocmapperincludes", + export_include_dirs: ["."], +} diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp new file mode 100644 index 0000000000..28f50161c7 --- /dev/null +++ b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp @@ -0,0 +1,156 @@ +/* + * Copyright 2016 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 "Gralloc0Mapper" + +#include "Gralloc0Mapper.h" + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace mapper { +namespace V2_0 { +namespace implementation { + +Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module) + : mModule(reinterpret_cast(module)), + mMinor(module->module_api_version & 0xff) { + mCapabilities.highUsageBits = false; + mCapabilities.layeredBuffers = false; + mCapabilities.unregisterImplyDelete = false; +} + +Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) { + int result = mModule->registerBuffer(mModule, bufferHandle); + return result ? Error::BAD_BUFFER : Error::NONE; +} + +void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) { + mModule->unregisterBuffer(mModule, bufferHandle); +} + +Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle, + uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + void** outData) { + int result; + void* data = nullptr; + if (mMinor >= 3 && mModule->lockAsync) { + // Dup fenceFd as it is going to be owned by gralloc. Note that it is + // gralloc's responsibility to close it, even on locking errors. + if (fenceFd >= 0) { + fenceFd = dup(fenceFd); + if (fenceFd < 0) { + return Error::NO_RESOURCES; + } + } + + result = mModule->lockAsync(mModule, bufferHandle, cpuUsage, + accessRegion.left, accessRegion.top, + accessRegion.width, accessRegion.height, + &data, fenceFd); + } else { + waitFenceFd(fenceFd, "Gralloc0Mapper::lock"); + + result = mModule->lock(mModule, bufferHandle, cpuUsage, + accessRegion.left, accessRegion.top, + accessRegion.width, accessRegion.height, &data); + } + + if (result) { + return Error::BAD_VALUE; + } else { + *outData = data; + return Error::NONE; + } +} + +Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle, + uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + YCbCrLayout* outLayout) { + int result; + android_ycbcr ycbcr = {}; + if (mMinor >= 3 && mModule->lockAsync_ycbcr) { + // Dup fenceFd as it is going to be owned by gralloc. Note that it is + // gralloc's responsibility to close it, even on locking errors. + if (fenceFd >= 0) { + fenceFd = dup(fenceFd); + if (fenceFd < 0) { + return Error::NO_RESOURCES; + } + } + + result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage, + accessRegion.left, accessRegion.top, + accessRegion.width, + accessRegion.height, &ycbcr, fenceFd); + } else { + waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr"); + + if (mModule->lock_ycbcr) { + result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage, + accessRegion.left, accessRegion.top, + accessRegion.width, + accessRegion.height, &ycbcr); + } else { + result = -EINVAL; + } + } + + if (result) { + return Error::BAD_VALUE; + } else { + outLayout->y = ycbcr.y; + outLayout->cb = ycbcr.cb; + outLayout->cr = ycbcr.cr; + outLayout->yStride = ycbcr.ystride; + outLayout->cStride = ycbcr.cstride; + outLayout->chromaStep = ycbcr.chroma_step; + return Error::NONE; + } +} + +Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle, + int* outFenceFd) { + int result; + int fenceFd = -1; + if (mMinor >= 3 && mModule->unlockAsync) { + result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd); + } else { + result = mModule->unlock(mModule, bufferHandle); + } + + if (result) { + // we always own the fenceFd even when unlock failed + if (fenceFd >= 0) { + close(fenceFd); + } + + return Error::BAD_VALUE; + } else { + *outFenceFd = fenceFd; + return Error::NONE; + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.h b/graphics/mapper/2.0/default/Gralloc0Mapper.h new file mode 100644 index 0000000000..e792a69703 --- /dev/null +++ b/graphics/mapper/2.0/default/Gralloc0Mapper.h @@ -0,0 +1,56 @@ +/* + * Copyright 2016 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_MAPPER_V2_0_GRALLOC0MAPPER_H +#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H + +#include "GrallocMapper.h" + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace mapper { +namespace V2_0 { +namespace implementation { + +class Gralloc0Mapper : public GrallocMapper { + public: + Gralloc0Mapper(const hw_module_t* module); + + private: + Error registerBuffer(buffer_handle_t bufferHandle) override; + void unregisterBuffer(buffer_handle_t bufferHandle) override; + Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + void** outData) override; + Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + YCbCrLayout* outLayout) override; + Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override; + + const gralloc_module_t* mModule; + uint8_t mMinor; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp new file mode 100644 index 0000000000..c1e5adcd64 --- /dev/null +++ b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp @@ -0,0 +1,273 @@ +/* + * Copyright 2016 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 "Gralloc1Mapper" + +#include "Gralloc1Mapper.h" + +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace mapper { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::common::V1_0::BufferUsage; + +Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module) + : mDevice(nullptr), mDispatch() { + int result = gralloc1_open(module, &mDevice); + if (result) { + LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s", + strerror(-result)); + } + + initCapabilities(); + initDispatch(); +} + +Gralloc1Mapper::~Gralloc1Mapper() { + gralloc1_close(mDevice); +} + +void Gralloc1Mapper::initCapabilities() { + mCapabilities.highUsageBits = true; + mCapabilities.layeredBuffers = false; + mCapabilities.unregisterImplyDelete = false; + + uint32_t count = 0; + mDevice->getCapabilities(mDevice, &count, nullptr); + + std::vector capabilities(count); + mDevice->getCapabilities(mDevice, &count, capabilities.data()); + capabilities.resize(count); + + for (auto capability : capabilities) { + switch (capability) { + case GRALLOC1_CAPABILITY_LAYERED_BUFFERS: + mCapabilities.layeredBuffers = true; + break; + case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE: + mCapabilities.unregisterImplyDelete = true; + break; + } + } +} + +template +void Gralloc1Mapper::initDispatch(gralloc1_function_descriptor_t desc, + T* outPfn) { + auto pfn = mDevice->getFunction(mDevice, desc); + if (!pfn) { + LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc); + } + + *outPfn = reinterpret_cast(pfn); +} + +void Gralloc1Mapper::initDispatch() { + initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain); + initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release); + initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, + &mDispatch.getNumFlexPlanes); + initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock); + initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex); + initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock); +} + +Error Gralloc1Mapper::toError(int32_t error) { + switch (error) { + case GRALLOC1_ERROR_NONE: + return Error::NONE; + case GRALLOC1_ERROR_BAD_DESCRIPTOR: + return Error::BAD_DESCRIPTOR; + case GRALLOC1_ERROR_BAD_HANDLE: + return Error::BAD_BUFFER; + case GRALLOC1_ERROR_BAD_VALUE: + return Error::BAD_VALUE; + case GRALLOC1_ERROR_NOT_SHARED: + return Error::NONE; // this is fine + case GRALLOC1_ERROR_NO_RESOURCES: + return Error::NO_RESOURCES; + case GRALLOC1_ERROR_UNDEFINED: + case GRALLOC1_ERROR_UNSUPPORTED: + default: + return Error::UNSUPPORTED; + } +} + +bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex, + YCbCrLayout* outLayout) { + // must be YCbCr + if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) { + return false; + } + + for (int i = 0; i < 3; i++) { + const auto& plane = flex.planes[i]; + // must have 8-bit depth + if (plane.bits_per_component != 8 || plane.bits_used != 8) { + return false; + } + + if (plane.component == FLEX_COMPONENT_Y) { + // Y must not be interleaved + if (plane.h_increment != 1) { + return false; + } + } else { + // Cb and Cr can be interleaved + if (plane.h_increment != 1 && plane.h_increment != 2) { + return false; + } + } + + if (!plane.v_increment) { + return false; + } + } + + if (flex.planes[0].component != FLEX_COMPONENT_Y || + flex.planes[1].component != FLEX_COMPONENT_Cb || + flex.planes[2].component != FLEX_COMPONENT_Cr) { + return false; + } + + const auto& y = flex.planes[0]; + const auto& cb = flex.planes[1]; + const auto& cr = flex.planes[2]; + + if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) { + return false; + } + + outLayout->y = y.top_left; + outLayout->cb = cb.top_left; + outLayout->cr = cr.top_left; + outLayout->yStride = y.v_increment; + outLayout->cStride = cb.v_increment; + outLayout->chromaStep = cb.h_increment; + + return true; +} + +gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) { + return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height}; +} + +Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) { + return toError(mDispatch.retain(mDevice, bufferHandle)); +} + +void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) { + mDispatch.release(mDevice, bufferHandle); +} + +Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle, + uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + void** outData) { + // Dup fenceFd as it is going to be owned by gralloc. Note that it is + // gralloc's responsibility to close it, even on locking errors. + if (fenceFd >= 0) { + fenceFd = dup(fenceFd); + if (fenceFd < 0) { + return Error::NO_RESOURCES; + } + } + + const uint64_t consumerUsage = + cpuUsage & ~static_cast(BufferUsage::CPU_WRITE_MASK); + const auto accessRect = asGralloc1Rect(accessRegion); + void* data = nullptr; + int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage, + consumerUsage, &accessRect, &data, fenceFd); + + if (error == GRALLOC1_ERROR_NONE) { + *outData = data; + } + + return toError(error); +} + +Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle, + uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + YCbCrLayout* outLayout) { + // prepare flex layout + android_flex_layout flex = {}; + int32_t error = + mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes); + if (error != GRALLOC1_ERROR_NONE) { + return toError(error); + } + std::vector flexPlanes(flex.num_planes); + flex.planes = flexPlanes.data(); + + // Dup fenceFd as it is going to be owned by gralloc. Note that it is + // gralloc's responsibility to close it, even on locking errors. + if (fenceFd >= 0) { + fenceFd = dup(fenceFd); + if (fenceFd < 0) { + return Error::NO_RESOURCES; + } + } + + const uint64_t consumerUsage = + cpuUsage & ~static_cast(BufferUsage::CPU_WRITE_MASK); + const auto accessRect = asGralloc1Rect(accessRegion); + error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage, + &accessRect, &flex, fenceFd); + if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) { + ALOGD("unable to convert android_flex_layout to YCbCrLayout"); + + // undo the lock + fenceFd = -1; + mDispatch.unlock(mDevice, bufferHandle, &fenceFd); + if (fenceFd >= 0) { + close(fenceFd); + } + + error = GRALLOC1_ERROR_BAD_HANDLE; + } + + return toError(error); +} + +Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle, + int* outFenceFd) { + int fenceFd = -1; + int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd); + + if (error == GRALLOC1_ERROR_NONE) { + *outFenceFd = fenceFd; + } else if (fenceFd >= 0) { + // we always own the fenceFd even when unlock failed + close(fenceFd); + } + + return toError(error); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.h b/graphics/mapper/2.0/default/Gralloc1Mapper.h new file mode 100644 index 0000000000..452afdf820 --- /dev/null +++ b/graphics/mapper/2.0/default/Gralloc1Mapper.h @@ -0,0 +1,76 @@ +/* + * Copyright 2016 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_MAPPER_V2_0_GRALLOC1MAPPER_H +#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H + +#include "GrallocMapper.h" + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace mapper { +namespace V2_0 { +namespace implementation { + +class Gralloc1Mapper : public GrallocMapper { + public: + Gralloc1Mapper(const hw_module_t* module); + ~Gralloc1Mapper(); + + private: + void initCapabilities(); + + template + void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn); + void initDispatch(); + + static Error toError(int32_t error); + static bool toYCbCrLayout(const android_flex_layout& flex, + YCbCrLayout* outLayout); + static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect); + + Error registerBuffer(buffer_handle_t bufferHandle) override; + void unregisterBuffer(buffer_handle_t bufferHandle) override; + Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + void** outData) override; + Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + YCbCrLayout* outLayout) override; + Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override; + + gralloc1_device_t* mDevice; + + struct { + GRALLOC1_PFN_RETAIN retain; + GRALLOC1_PFN_RELEASE release; + GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes; + GRALLOC1_PFN_LOCK lock; + GRALLOC1_PFN_LOCK_FLEX lockFlex; + GRALLOC1_PFN_UNLOCK unlock; + } mDispatch; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H diff --git a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h new file mode 100644 index 0000000000..9b5ab04562 --- /dev/null +++ b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h @@ -0,0 +1,79 @@ +/* + * Copyright 2016 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_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H +#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace mapper { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::common::V1_0::PixelFormat; + +/** + * BufferDescriptor is created by IMapper and consumed by IAllocator. It is + * versioned so that IMapper and IAllocator can be updated independently. + */ +constexpr uint32_t grallocBufferDescriptorSize = 7; +constexpr uint32_t grallocBufferDescriptorMagicVersion = ((0x9487 << 16) | 0); + +inline BufferDescriptor grallocEncodeBufferDescriptor( + const IMapper::BufferDescriptorInfo& descriptorInfo) { + BufferDescriptor descriptor; + descriptor.resize(grallocBufferDescriptorSize); + descriptor[0] = grallocBufferDescriptorMagicVersion; + descriptor[1] = descriptorInfo.width; + descriptor[2] = descriptorInfo.height; + descriptor[3] = descriptorInfo.layerCount; + descriptor[4] = static_cast(descriptorInfo.format); + descriptor[5] = static_cast(descriptorInfo.usage); + descriptor[6] = static_cast(descriptorInfo.usage >> 32); + + return descriptor; +} + +inline bool grallocDecodeBufferDescriptor( + const BufferDescriptor& descriptor, + IMapper::BufferDescriptorInfo* outDescriptorInfo) { + if (descriptor.size() != grallocBufferDescriptorSize || + descriptor[0] != grallocBufferDescriptorMagicVersion) { + return false; + } + + *outDescriptorInfo = IMapper::BufferDescriptorInfo{ + descriptor[1], + descriptor[2], + descriptor[3], + static_cast(descriptor[4]), + (static_cast(descriptor[6]) << 32) | descriptor[5], + }; + + return true; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp index 526aca23b6..339317aff8 100644 --- a/graphics/mapper/2.0/default/GrallocMapper.cpp +++ b/graphics/mapper/2.0/default/GrallocMapper.cpp @@ -17,14 +17,14 @@ #include "GrallocMapper.h" -#include -#include -#include +#include "Gralloc0Mapper.h" +#include "Gralloc1Mapper.h" +#include "GrallocBufferDescriptor.h" -#include +#include -#include #include +#include namespace android { namespace hardware { @@ -33,374 +33,251 @@ namespace mapper { namespace V2_0 { namespace implementation { -namespace { - -using android::hardware::graphics::allocator::V2_0::Error; +using android::hardware::graphics::common::V1_0::BufferUsage; using android::hardware::graphics::common::V1_0::PixelFormat; -class GrallocMapperHal : public IMapper { -public: - GrallocMapperHal(const hw_module_t* module); - ~GrallocMapperHal(); +std::mutex GrallocMapper::mMutex; +std::unordered_set GrallocMapper::mRegisteredHandles; - // IMapper interface - Return retain(const hidl_handle& bufferHandle) override; - Return release(const hidl_handle& bufferHandle) override; - Return getDimensions(const hidl_handle& bufferHandle, - getDimensions_cb hidl_cb) override; - Return getFormat(const hidl_handle& bufferHandle, - getFormat_cb hidl_cb) override; - Return getLayerCount(const hidl_handle& bufferHandle, - getLayerCount_cb hidl_cb) override; - Return getProducerUsageMask(const hidl_handle& bufferHandle, - getProducerUsageMask_cb hidl_cb) override; - Return getConsumerUsageMask(const hidl_handle& bufferHandle, - getConsumerUsageMask_cb hidl_cb) override; - Return getBackingStore(const hidl_handle& bufferHandle, - getBackingStore_cb hidl_cb) override; - Return getStride(const hidl_handle& bufferHandle, - getStride_cb hidl_cb) override; - Return lock(const hidl_handle& bufferHandle, - uint64_t producerUsageMask, uint64_t consumerUsageMask, - const IMapper::Rect& accessRegion, const hidl_handle& acquireFence, - lock_cb hidl_cb) override; - Return lockFlex(const hidl_handle& bufferHandle, - uint64_t producerUsageMask, uint64_t consumerUsageMask, - const IMapper::Rect& accessRegion, const hidl_handle& acquireFence, - lockFlex_cb hidl_cb) override; - Return unlock(const hidl_handle& bufferHandle, - unlock_cb hidl_cb) override; +bool GrallocMapper::validateDescriptorInfo( + const BufferDescriptorInfo& descriptorInfo) const { + const uint64_t validUsageBits = + BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | + BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET | + BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET | + BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR | + BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT | + BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT | + BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA | + BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK | + (mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI + : static_cast(0)); -private: - void initCapabilities(); - - template - void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn); - void initDispatch(); - - static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect); - static bool dupFence(const hidl_handle& fenceHandle, int* outFd); - - gralloc1_device_t* mDevice; - - struct { - bool layeredBuffers; - } mCapabilities; - - struct { - GRALLOC1_PFN_RETAIN retain; - GRALLOC1_PFN_RELEASE release; - GRALLOC1_PFN_GET_DIMENSIONS getDimensions; - GRALLOC1_PFN_GET_FORMAT getFormat; - GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount; - GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage; - GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage; - GRALLOC1_PFN_GET_BACKING_STORE getBackingStore; - GRALLOC1_PFN_GET_STRIDE getStride; - GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes; - GRALLOC1_PFN_LOCK lock; - GRALLOC1_PFN_LOCK_FLEX lockFlex; - GRALLOC1_PFN_UNLOCK unlock; - } mDispatch; - - std::mutex mMutex; - std::unordered_map mBufferReferenceCounts; -}; - -GrallocMapperHal::GrallocMapperHal(const hw_module_t* module) - : mDevice(nullptr), mCapabilities(), mDispatch() -{ - int status = gralloc1_open(module, &mDevice); - if (status) { - LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s", - strerror(-status)); - } - - initCapabilities(); - initDispatch(); -} - -GrallocMapperHal::~GrallocMapperHal() -{ - gralloc1_close(mDevice); -} - -void GrallocMapperHal::initCapabilities() -{ - uint32_t count = 0; - mDevice->getCapabilities(mDevice, &count, nullptr); - - std::vector caps(count); - mDevice->getCapabilities(mDevice, &count, caps.data()); - caps.resize(count); - - for (auto cap : caps) { - switch (cap) { - case GRALLOC1_CAPABILITY_LAYERED_BUFFERS: - mCapabilities.layeredBuffers = true; - break; - default: - break; - } - } -} - -template -void GrallocMapperHal::initDispatch(gralloc1_function_descriptor_t desc, - T* outPfn) -{ - auto pfn = mDevice->getFunction(mDevice, desc); - if (!pfn) { - LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc); - } - - *outPfn = reinterpret_cast(pfn); -} - -void GrallocMapperHal::initDispatch() -{ - initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain); - initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release); - initDispatch(GRALLOC1_FUNCTION_GET_DIMENSIONS, &mDispatch.getDimensions); - initDispatch(GRALLOC1_FUNCTION_GET_FORMAT, &mDispatch.getFormat); - if (mCapabilities.layeredBuffers) { - initDispatch(GRALLOC1_FUNCTION_GET_LAYER_COUNT, - &mDispatch.getLayerCount); - } - initDispatch(GRALLOC1_FUNCTION_GET_PRODUCER_USAGE, - &mDispatch.getProducerUsage); - initDispatch(GRALLOC1_FUNCTION_GET_CONSUMER_USAGE, - &mDispatch.getConsumerUsage); - initDispatch(GRALLOC1_FUNCTION_GET_BACKING_STORE, - &mDispatch.getBackingStore); - initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride); - initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, - &mDispatch.getNumFlexPlanes); - initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock); - initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex); - initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock); -} - -gralloc1_rect_t GrallocMapperHal::asGralloc1Rect(const IMapper::Rect& rect) -{ - return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height}; -} - -bool GrallocMapperHal::dupFence(const hidl_handle& fenceHandle, int* outFd) -{ - auto handle = fenceHandle.getNativeHandle(); - if (!handle || handle->numFds == 0) { - *outFd = -1; - return true; - } - - if (handle->numFds > 1) { - ALOGE("invalid fence handle with %d fds", handle->numFds); + if (!descriptorInfo.width || !descriptorInfo.height || + !descriptorInfo.layerCount) { return false; } - *outFd = dup(handle->data[0]); - return (*outFd >= 0); -} - -Return GrallocMapperHal::retain(const hidl_handle& bufferHandle) -{ - int32_t err = mDispatch.retain(mDevice, bufferHandle); - if (err == GRALLOC1_ERROR_NONE) { - auto nativeHandle = bufferHandle.getNativeHandle(); - std::lock_guard lock(mMutex); - - ++mBufferReferenceCounts[nativeHandle]; - } - return static_cast(err); -} - -Return GrallocMapperHal::release(const hidl_handle& bufferHandle) -{ - int32_t err = mDispatch.release(mDevice, bufferHandle); - if (err == GRALLOC1_ERROR_NONE) { - auto nativeHandle = bufferHandle.getNativeHandle(); - std::lock_guard lock(mMutex); - - auto iter = mBufferReferenceCounts.find(bufferHandle); - if (iter == mBufferReferenceCounts.end()) { - // this should never happen - err = GRALLOC1_ERROR_BAD_HANDLE; - } else if (--iter->second == 0) { - native_handle_close(nativeHandle); - native_handle_delete(const_cast(nativeHandle)); - - mBufferReferenceCounts.erase(iter); - } + if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) { + return false; } - return static_cast(err); -} - -Return GrallocMapperHal::getDimensions(const hidl_handle& bufferHandle, - getDimensions_cb hidl_cb) -{ - uint32_t width = 0; - uint32_t height = 0; - int32_t err = mDispatch.getDimensions(mDevice, bufferHandle, - &width, &height); - - hidl_cb(static_cast(err), width, height); - return Void(); -} - -Return GrallocMapperHal::getFormat(const hidl_handle& bufferHandle, - getFormat_cb hidl_cb) -{ - int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; - int32_t err = mDispatch.getFormat(mDevice, bufferHandle, &format); - - hidl_cb(static_cast(err), static_cast(format)); - return Void(); -} - -Return GrallocMapperHal::getLayerCount(const hidl_handle& bufferHandle, - getLayerCount_cb hidl_cb) -{ - int32_t err = GRALLOC1_ERROR_NONE; - uint32_t count = 1; - if (mCapabilities.layeredBuffers) { - err = mDispatch.getLayerCount(mDevice, bufferHandle, &count); + if (descriptorInfo.format == static_cast(0)) { + return false; + } + + if (descriptorInfo.usage & ~validUsageBits) { + // could not fail as gralloc may use the reserved bits... + ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64, + descriptorInfo.usage & ~validUsageBits); + } + + return true; +} + +Return GrallocMapper::createDescriptor( + const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) { + if (validateDescriptorInfo(descriptorInfo)) { + hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo)); + } else { + hidl_cb(Error::BAD_VALUE, BufferDescriptor()); } - hidl_cb(static_cast(err), count); return Void(); } -Return GrallocMapperHal::getProducerUsageMask( - const hidl_handle& bufferHandle, getProducerUsageMask_cb hidl_cb) -{ - uint64_t mask = 0x0; - int32_t err = mDispatch.getProducerUsage(mDevice, bufferHandle, &mask); - - hidl_cb(static_cast(err), mask); - return Void(); +bool GrallocMapper::addRegisteredHandle(buffer_handle_t bufferHandle) { + std::lock_guard lock(mMutex); + return mRegisteredHandles.insert(bufferHandle).second; } -Return GrallocMapperHal::getConsumerUsageMask( - const hidl_handle& bufferHandle, getConsumerUsageMask_cb hidl_cb) -{ - uint64_t mask = 0x0; - int32_t err = mDispatch.getConsumerUsage(mDevice, bufferHandle, &mask); +native_handle_t* GrallocMapper::popRegisteredHandle(void* buffer) { + auto bufferHandle = static_cast(buffer); - hidl_cb(static_cast(err), mask); - return Void(); + std::lock_guard lock(mMutex); + return mRegisteredHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr; } -Return GrallocMapperHal::getBackingStore( - const hidl_handle& bufferHandle, getBackingStore_cb hidl_cb) -{ - uint64_t store = 0; - int32_t err = mDispatch.getBackingStore(mDevice, bufferHandle, &store); +buffer_handle_t GrallocMapper::getRegisteredHandle(const void* buffer) { + auto bufferHandle = static_cast(buffer); - hidl_cb(static_cast(err), store); - return Void(); + std::lock_guard lock(mMutex); + return mRegisteredHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr; } -Return GrallocMapperHal::getStride(const hidl_handle& bufferHandle, - getStride_cb hidl_cb) -{ - uint32_t stride = 0; - int32_t err = mDispatch.getStride(mDevice, bufferHandle, &stride); +Return GrallocMapper::importBuffer(const hidl_handle& rawHandle, + importBuffer_cb hidl_cb) { + // importing an already imported handle rather than a raw handle + if (getRegisteredHandle(rawHandle.getNativeHandle())) { + hidl_cb(Error::BAD_BUFFER, nullptr); + return Void(); + } - hidl_cb(static_cast(err), stride); - return Void(); -} + if (!rawHandle.getNativeHandle()) { + hidl_cb(Error::BAD_BUFFER, nullptr); + return Void(); + } -Return GrallocMapperHal::lock(const hidl_handle& bufferHandle, - uint64_t producerUsageMask, uint64_t consumerUsageMask, - const IMapper::Rect& accessRegion, const hidl_handle& acquireFence, - lock_cb hidl_cb) -{ - gralloc1_rect_t rect = asGralloc1Rect(accessRegion); - - int fence = -1; - if (!dupFence(acquireFence, &fence)) { + native_handle_t* bufferHandle = + native_handle_clone(rawHandle.getNativeHandle()); + if (!bufferHandle) { hidl_cb(Error::NO_RESOURCES, nullptr); return Void(); } + Error error = registerBuffer(bufferHandle); + if (error != Error::NONE) { + native_handle_close(bufferHandle); + native_handle_delete(bufferHandle); + + hidl_cb(error, nullptr); + return Void(); + } + + // The newly cloned handle is already registered? This can only happen + // when a handle previously registered was native_handle_delete'd instead + // of freeBuffer'd. + if (!addRegisteredHandle(bufferHandle)) { + ALOGE("handle %p has already been imported; potential fd leaking", + bufferHandle); + unregisterBuffer(bufferHandle); + if (!mCapabilities.unregisterImplyDelete) { + native_handle_close(bufferHandle); + native_handle_delete(bufferHandle); + } + + hidl_cb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + hidl_cb(Error::NONE, bufferHandle); + return Void(); +} + +Return GrallocMapper::freeBuffer(void* buffer) { + native_handle_t* bufferHandle = popRegisteredHandle(buffer); + if (!bufferHandle) { + return Error::BAD_BUFFER; + } + + unregisterBuffer(bufferHandle); + if (!mCapabilities.unregisterImplyDelete) { + native_handle_close(bufferHandle); + native_handle_delete(bufferHandle); + } + + return Error::NONE; +} + +void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) { + if (fenceFd < 0) { + return; + } + + const int warningTimeout = 3500; + const int error = sync_wait(fenceFd, warningTimeout); + if (error < 0 && errno == ETIME) { + ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd, + warningTimeout); + sync_wait(fenceFd, -1); + } +} + +bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle, + int* outFenceFd) { + auto handle = fenceHandle.getNativeHandle(); + if (handle && handle->numFds > 1) { + ALOGE("invalid fence handle with %d fds", handle->numFds); + return false; + } + + *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1; + return true; +} + +hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) { + native_handle_t* handle = nullptr; + if (fenceFd >= 0) { + handle = native_handle_init(handleStorage, 1, 0); + handle->data[0] = fenceFd; + } + + return hidl_handle(handle); +} + +Return GrallocMapper::lock(void* buffer, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, + const hidl_handle& acquireFence, + lock_cb hidl_cb) { + buffer_handle_t bufferHandle = getRegisteredHandle(buffer); + if (!bufferHandle) { + hidl_cb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + int fenceFd; + if (!getFenceFd(acquireFence, &fenceFd)) { + hidl_cb(Error::BAD_VALUE, nullptr); + return Void(); + } + void* data = nullptr; - int32_t err = mDispatch.lock(mDevice, bufferHandle, producerUsageMask, - consumerUsageMask, &rect, &data, fence); - if (err != GRALLOC1_ERROR_NONE) { - close(fence); - } + Error error = + lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data); - hidl_cb(static_cast(err), data); + hidl_cb(error, data); return Void(); } -Return GrallocMapperHal::lockFlex(const hidl_handle& bufferHandle, - uint64_t producerUsageMask, uint64_t consumerUsageMask, - const IMapper::Rect& accessRegion, const hidl_handle& acquireFence, - lockFlex_cb hidl_cb) -{ - FlexLayout layout_reply{}; +Return GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, + const hidl_handle& acquireFence, + lockYCbCr_cb hidl_cb) { + YCbCrLayout layout = {}; - uint32_t planeCount = 0; - int32_t err = mDispatch.getNumFlexPlanes(mDevice, bufferHandle, - &planeCount); - if (err != GRALLOC1_ERROR_NONE) { - hidl_cb(static_cast(err), layout_reply); + buffer_handle_t bufferHandle = getRegisteredHandle(buffer); + if (!bufferHandle) { + hidl_cb(Error::BAD_BUFFER, layout); return Void(); } - gralloc1_rect_t rect = asGralloc1Rect(accessRegion); - - int fence = -1; - if (!dupFence(acquireFence, &fence)) { - hidl_cb(Error::NO_RESOURCES, layout_reply); + int fenceFd; + if (!getFenceFd(acquireFence, &fenceFd)) { + hidl_cb(Error::BAD_VALUE, layout); return Void(); } - std::vector planes(planeCount); - android_flex_layout_t layout{}; - layout.num_planes = planes.size(); - layout.planes = planes.data(); + Error error = + lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout); - err = mDispatch.lockFlex(mDevice, bufferHandle, producerUsageMask, - consumerUsageMask, &rect, &layout, fence); - if (err == GRALLOC1_ERROR_NONE) { - layout_reply.format = static_cast(layout.format); + hidl_cb(error, layout); + return Void(); +} - planes.resize(layout.num_planes); - layout_reply.planes.setToExternal( - reinterpret_cast(planes.data()), planes.size()); +Return GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) { + buffer_handle_t bufferHandle = getRegisteredHandle(buffer); + if (!bufferHandle) { + hidl_cb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + int fenceFd; + Error error = unlockBuffer(bufferHandle, &fenceFd); + if (error == Error::NONE) { + NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0); + + hidl_cb(error, getFenceHandle(fenceFd, fenceStorage)); + + if (fenceFd >= 0) { + close(fenceFd); + } } else { - close(fence); + hidl_cb(error, nullptr); } - hidl_cb(static_cast(err), layout_reply); return Void(); } -Return GrallocMapperHal::unlock(const hidl_handle& bufferHandle, - unlock_cb hidl_cb) -{ - int32_t fence = -1; - int32_t err = mDispatch.unlock(mDevice, bufferHandle, &fence); - - NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0); - hidl_handle fenceHandle; - if (err == GRALLOC1_ERROR_NONE && fence >= 0) { - auto nativeHandle = native_handle_init(fenceStorage, 1, 0); - nativeHandle->data[0] = fence; - - fenceHandle = nativeHandle; - } - - hidl_cb(static_cast(err), fenceHandle); - return Void(); -} - -} // anonymous namespace - IMapper* HIDL_FETCH_IMapper(const char* /* name */) { const hw_module_t* module = nullptr; int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); @@ -410,12 +287,15 @@ IMapper* HIDL_FETCH_IMapper(const char* /* name */) { } uint8_t major = (module->module_api_version >> 8) & 0xff; - if (major != 1) { - ALOGE("unknown gralloc module major version %d", major); - return nullptr; + switch (major) { + case 1: + return new Gralloc1Mapper(module); + case 0: + return new Gralloc0Mapper(module); + default: + ALOGE("unknown gralloc module major version %d", major); + return nullptr; } - - return new GrallocMapperHal(module); } } // namespace implementation diff --git a/graphics/mapper/2.0/default/GrallocMapper.h b/graphics/mapper/2.0/default/GrallocMapper.h index a2f89d16ac..c9c6d8a918 100644 --- a/graphics/mapper/2.0/default/GrallocMapper.h +++ b/graphics/mapper/2.0/default/GrallocMapper.h @@ -18,6 +18,10 @@ #define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H #include +#include + +#include +#include namespace android { namespace hardware { @@ -26,6 +30,68 @@ namespace mapper { namespace V2_0 { namespace implementation { +class GrallocMapper : public IMapper { + public: + // IMapper interface + Return createDescriptor(const BufferDescriptorInfo& descriptorInfo, + createDescriptor_cb hidl_cb) override; + Return importBuffer(const hidl_handle& rawHandle, + importBuffer_cb hidl_cb) override; + Return freeBuffer(void* buffer) override; + Return lock(void* buffer, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, + const hidl_handle& acquireFence, + lock_cb hidl_cb) override; + Return lockYCbCr(void* buffer, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, + const hidl_handle& acquireFence, + lockYCbCr_cb hidl_cb) override; + Return unlock(void* buffer, unlock_cb hidl_cb) override; + + protected: + static void waitFenceFd(int fenceFd, const char* logname); + + struct { + bool highUsageBits; + bool layeredBuffers; + bool unregisterImplyDelete; + } mCapabilities = {}; + + private: + virtual bool validateDescriptorInfo( + const BufferDescriptorInfo& descriptorInfo) const; + + // Register a buffer. The handle is already cloned by the caller. + virtual Error registerBuffer(buffer_handle_t bufferHandle) = 0; + + // Unregister a buffer. The handle is closed and deleted by the + // callee if and only if mCapabilities.unregisterImplyDelete is set. + virtual void unregisterBuffer(buffer_handle_t bufferHandle) = 0; + + // Lock a buffer. The fence is owned by the caller. + virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + void** outData) = 0; + virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int fenceFd, + YCbCrLayout* outLayout) = 0; + + // Unlock a buffer. The returned fence is owned by the caller. + virtual Error unlockBuffer(buffer_handle_t bufferHandle, + int* outFenceFd) = 0; + + static bool addRegisteredHandle(buffer_handle_t bufferHandle); + static buffer_handle_t getRegisteredHandle(const void* buffer); + static native_handle_t* popRegisteredHandle(void* buffer); + + static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd); + static hidl_handle getFenceHandle(int fenceFd, char* handleStorage); + + // these are static and shared by all mappers + static std::mutex mMutex; + static std::unordered_set mRegisteredHandles; +}; + extern "C" IMapper* HIDL_FETCH_IMapper(const char* name); } // namespace implementation diff --git a/graphics/mapper/2.0/types.hal b/graphics/mapper/2.0/types.hal index 2946e85e3e..e9b2f3a76c 100644 --- a/graphics/mapper/2.0/types.hal +++ b/graphics/mapper/2.0/types.hal @@ -16,101 +16,50 @@ package android.hardware.graphics.mapper@2.0; +enum Error : int32_t { + NONE = 0, /** no error */ + BAD_DESCRIPTOR = 1, /** invalid BufferDescriptor */ + BAD_BUFFER = 2, /** invalid buffer handle */ + BAD_VALUE = 3, /** invalid width, height, etc. */ + /* 4 is reserved */ + NO_RESOURCES = 5, /** temporary failure due to resource contention */ + /* 6 is reserved */ + UNSUPPORTED = 7, /** permanent failure */ +}; + /** - * Structures for describing flexible YUVA/RGBA formats for consumption by - * applications. Such flexible formats contain a plane for each component (e.g. - * red, green, blue), where each plane is laid out in a grid-like pattern - * occupying unique byte addresses and with consistent byte offsets between - * neighboring pixels. - * - * The FlexLayout structure is used with any pixel format that can be - * represented by it, such as: - * - PixelFormat::YCBCR_*_888 - * - PixelFormat::FLEX_RGB*_888 - * - PixelFormat::RGB[AX]_888[8],BGRA_8888,RGB_888 - * - PixelFormat::YV12,Y8,Y16,YCBCR_422_SP/I,YCRCB_420_SP - * - even implementation defined formats that can be represented by - * the structures - * - * Vertical increment (aka. row increment or stride) describes the distance in - * bytes from the first pixel of one row to the first pixel of the next row - * (below) for the component plane. This can be negative. - * - * Horizontal increment (aka. column or pixel increment) describes the distance - * in bytes from one pixel to the next pixel (to the right) on the same row for - * the component plane. This can be negative. - * - * Each plane can be subsampled either vertically or horizontally by - * a power-of-two factor. - * - * The bit-depth of each component can be arbitrary, as long as the pixels are - * laid out on whole bytes, in native byte-order, using the most significant - * bits of each unit. + * A buffer descriptor is an implementation-defined opaque data returned by + * createDescriptor. It describes the properties of a buffer and is consumed + * by the allocator. */ +typedef vec BufferDescriptor; -enum FlexComponent : int32_t { - Y = 1 << 0, /** luma */ - CB = 1 << 1, /** chroma blue */ - CR = 1 << 2, /** chroma red */ - - R = 1 << 10, /** red */ - G = 1 << 11, /** green */ - B = 1 << 12, /** blue */ - - A = 1 << 30, /** alpha */ +/** + * Structure for describing YCbCr formats for consumption by applications. + * This is used with PixelFormat::YCBCR_*_888. + * + * Buffer chroma subsampling is defined in the format. + * e.g. PixelFormat::YCBCR_420_888 has subsampling 4:2:0. + * + * Buffers must have a 8 bit depth. + * + * y, cb, and cr point to the first byte of their respective planes. + * + * Stride describes the distance in bytes from the first value of one row of + * the image to the first value of the next row. It includes the width of the + * image plus padding. + * yStride is the stride of the luma plane. + * cStride is the stride of the chroma planes. + * + * chromaStep is the distance in bytes from one chroma pixel value to the + * next. This is 2 bytes for semiplanar (because chroma values are interleaved + * and each chroma value is one byte) and 1 for planar. + */ +struct YCbCrLayout { + pointer y; + pointer cb; + pointer cr; + uint32_t yStride; + uint32_t cStride; + uint32_t chromaStep; }; - -enum FlexFormat : int32_t { - /** not a flexible format */ - INVALID = 0x0, - - Y = FlexComponent:Y, - YCBCR = Y | FlexComponent:CB | FlexComponent:CR, - YCBCRA = YCBCR | FlexComponent:A, - - RGB = FlexComponent:R | FlexComponent:G | FlexComponent:B, - RGBA = RGB | FlexComponent:A, -}; - -struct FlexPlane { - /** Pointer to the first byte of the top-left pixel of the plane. */ - pointer topLeft; - - FlexComponent component; - - /** - * Bits allocated for the component in each pixel. Must be a positive - * multiple of 8. - */ - int32_t bitsPerComponent; - - /** - * Number of the most significant bits used in the format for this - * component. Must be between 1 and bitsPerComponent, inclusive. - */ - int32_t bitsUsed; - - /** Horizontal increment. */ - int32_t hIncrement; - /** Vertical increment. */ - int32_t vIncrement; - /** Horizontal subsampling. Must be a positive power of 2. */ - int32_t hSubsampling; - /** Vertical subsampling. Must be a positive power of 2. */ - int32_t vSubsampling; -}; - -struct FlexLayout { - /** The kind of flexible format. */ - FlexFormat format; - - /** - * A plane for each component; ordered in increasing component value - * order. E.g. FlexFormat::RGBA maps 0 -> R, 1 -> G, etc. Can have size 0 - * for FlexFormat::INVALID. - */ - vec planes; -}; - -/** Backing store ID of a buffer. See IMapper::getBackingStore. */ -typedef uint64_t BackingStore; diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp index e26f087213..1c0e4c5a32 100644 --- a/graphics/mapper/2.0/vts/functional/Android.bp +++ b/graphics/mapper/2.0/vts/functional/Android.bp @@ -24,7 +24,6 @@ cc_library_static { ], static_libs: [ "VtsHalHidlTargetTestBase", - "libVtsHalGraphicsAllocatorTestUtils", ], cflags: [ "-Wall", @@ -54,7 +53,6 @@ cc_test { "android.hardware.graphics.common@1.0", ], static_libs: [ - "libVtsHalGraphicsAllocatorTestUtils", "libVtsHalGraphicsMapperTestUtils", "VtsHalHidlTargetTestBase", ], diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp index f6a26ac80e..c534889fca 100644 --- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp +++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp @@ -25,228 +25,233 @@ namespace mapper { namespace V2_0 { namespace tests { -using android::hardware::graphics::allocator::V2_0::Buffer; -using android::hardware::graphics::allocator::V2_0::BufferDescriptor; -using android::hardware::graphics::allocator::V2_0::Error; - -Mapper::Mapper() { init(); } - -void Mapper::init() { - mMapper = ::testing::VtsHalHidlTargetTestBase::getService(); - ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service"; - ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode"; +Gralloc::Gralloc() { + init(); } -Mapper::~Mapper() { - for (auto it : mHandles) { - while (it.second) { - EXPECT_EQ(Error::NONE, mMapper->release(it.first)) - << "failed to release handle " << it.first; - it.second--; +void Gralloc::init() { + mAllocator = ::testing::VtsHalHidlTargetTestBase::getService(); + ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service"; + + mMapper = ::testing::VtsHalHidlTargetTestBase::getService(); + ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service"; + ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode"; +} + +Gralloc::~Gralloc() { + for (auto bufferHandle : mClonedBuffers) { + auto buffer = const_cast(bufferHandle); + native_handle_close(buffer); + native_handle_delete(buffer); } - } - mHandles.clear(); + mClonedBuffers.clear(); + + for (auto bufferHandle : mImportedBuffers) { + auto buffer = const_cast(bufferHandle); + EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) + << "failed to free buffer " << buffer; + } + mImportedBuffers.clear(); } -sp Mapper::getRaw() const { return mMapper; } - -void Mapper::retain(const native_handle_t* handle) { - Error error = mMapper->retain(handle); - ASSERT_EQ(Error::NONE, error) << "failed to retain handle " << handle; - - mHandles[handle]++; +sp Gralloc::getAllocator() const { + return mAllocator; } -void Mapper::release(const native_handle_t* handle) { - Error error = mMapper->release(handle); - ASSERT_EQ(Error::NONE, error) << "failed to release handle " << handle; +std::string Gralloc::dumpDebugInfo() { + std::string debugInfo; + mAllocator->dumpDebugInfo( + [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); - if (--mHandles[handle] == 0) { - mHandles.erase(handle); - } + return debugInfo; } -Mapper::Dimensions Mapper::getDimensions(const native_handle_t* handle) { - Dimensions dimensions = {}; - mMapper->getDimensions(handle, [&](const auto& tmpError, const auto& tmpWidth, - const auto& tmpHeight) { - ASSERT_EQ(Error::NONE, tmpError) - << "failed to get dimensions for handle " << handle; - dimensions.width = tmpWidth; - dimensions.height = tmpHeight; - }); +const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) { + const native_handle_t* bufferHandle = + native_handle_clone(rawHandle.getNativeHandle()); + EXPECT_NE(nullptr, bufferHandle); - return dimensions; + if (bufferHandle) { + mClonedBuffers.insert(bufferHandle); + } + + return bufferHandle; } -PixelFormat Mapper::getFormat(const native_handle_t* handle) { - PixelFormat format = static_cast(0); - mMapper->getFormat(handle, [&](const auto& tmpError, const auto& tmpFormat) { - ASSERT_EQ(Error::NONE, tmpError) - << "failed to get format for handle " << handle; - format = tmpFormat; - }); +std::vector Gralloc::allocate( + const BufferDescriptor& descriptor, uint32_t count, bool import, + uint32_t* outStride) { + std::vector bufferHandles; + bufferHandles.reserve(count); + mAllocator->allocate( + descriptor, count, [&](const auto& tmpError, const auto& tmpStride, + const auto& tmpBuffers) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers"; + ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array"; - return format; + for (uint32_t i = 0; i < count; i++) { + if (import) { + ASSERT_NO_FATAL_FAILURE( + bufferHandles.push_back(importBuffer(tmpBuffers[i]))); + } else { + ASSERT_NO_FATAL_FAILURE( + bufferHandles.push_back(cloneBuffer(tmpBuffers[i]))); + } + } + + if (outStride) { + *outStride = tmpStride; + } + }); + + if (::testing::Test::HasFatalFailure()) { + bufferHandles.clear(); + } + + return bufferHandles; } -uint32_t Mapper::getLayerCount(const native_handle_t* handle) { - uint32_t count = 0; - mMapper->getLayerCount( - handle, [&](const auto& tmpError, const auto& tmpCount) { - ASSERT_EQ(Error::NONE, tmpError) - << "failed to get layer count for handle " << handle; - count = tmpCount; - }); +const native_handle_t* Gralloc::allocate( + const IMapper::BufferDescriptorInfo& descriptorInfo, bool import, + uint32_t* outStride) { + BufferDescriptor descriptor = createDescriptor(descriptorInfo); + if (::testing::Test::HasFatalFailure()) { + return nullptr; + } - return count; + auto buffers = allocate(descriptor, 1, import, outStride); + if (::testing::Test::HasFatalFailure()) { + return nullptr; + } + + return buffers[0]; } -uint64_t Mapper::getProducerUsageMask(const native_handle_t* handle) { - uint64_t usageMask = 0; - mMapper->getProducerUsageMask( - handle, [&](const auto& tmpError, const auto& tmpUsageMask) { - ASSERT_EQ(Error::NONE, tmpError) - << "failed to get producer usage mask for handle " << handle; - usageMask = tmpUsageMask; - }); - - return usageMask; +sp Gralloc::getMapper() const { + return mMapper; } -uint64_t Mapper::getConsumerUsageMask(const native_handle_t* handle) { - uint64_t usageMask = 0; - mMapper->getConsumerUsageMask( - handle, [&](const auto& tmpError, const auto& tmpUsageMask) { - ASSERT_EQ(Error::NONE, tmpError) - << "failed to get consumer usage mask for handle " << handle; - usageMask = tmpUsageMask; - }); +BufferDescriptor Gralloc::createDescriptor( + const IMapper::BufferDescriptorInfo& descriptorInfo) { + BufferDescriptor descriptor; + mMapper->createDescriptor( + descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor"; + descriptor = tmpDescriptor; + }); - return usageMask; + return descriptor; } -BackingStore Mapper::getBackingStore(const native_handle_t* handle) { - BackingStore backingStore = 0; - mMapper->getBackingStore( - handle, [&](const auto& tmpError, const auto& tmpBackingStore) { - ASSERT_EQ(Error::NONE, tmpError) - << "failed to get backing store for handle " << handle; - backingStore = tmpBackingStore; - }); +const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) { + const native_handle_t* bufferHandle = nullptr; + mMapper->importBuffer( + rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p" + << rawHandle.getNativeHandle(); + bufferHandle = static_cast(tmpBuffer); + }); - return backingStore; + if (bufferHandle) { + mImportedBuffers.insert(bufferHandle); + } + + return bufferHandle; } -uint32_t Mapper::getStride(const native_handle_t* handle) { - uint32_t stride = 0; - mMapper->getStride(handle, [&](const auto& tmpError, const auto& tmpStride) { - ASSERT_EQ(Error::NONE, tmpError) - << "failed to get stride for handle " << handle; - stride = tmpStride; - }); +void Gralloc::freeBuffer(const native_handle_t* bufferHandle) { + auto buffer = const_cast(bufferHandle); - return stride; + if (mImportedBuffers.erase(bufferHandle)) { + Error error = mMapper->freeBuffer(buffer); + ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer; + } else { + mClonedBuffers.erase(bufferHandle); + native_handle_close(buffer); + native_handle_delete(buffer); + } } -void* Mapper::lock(const native_handle_t* handle, uint64_t producerUsageMask, - uint64_t consumerUsageMask, - const IMapper::Rect& accessRegion, int acquireFence) { - NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1); - native_handle_t* acquireFenceHandle = nullptr; - if (acquireFence >= 0) { - acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1); - acquireFenceHandle->data[0] = acquireFence; - } +void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int acquireFence) { + auto buffer = const_cast(bufferHandle); - void* data = nullptr; - mMapper->lock( - handle, producerUsageMask, consumerUsageMask, accessRegion, - acquireFenceHandle, [&](const auto& tmpError, const auto& tmpData) { - ASSERT_EQ(Error::NONE, tmpError) << "failed to lock handle " << handle; - data = tmpData; - }); + NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0); + hidl_handle acquireFenceHandle; + if (acquireFence >= 0) { + auto h = native_handle_init(acquireFenceStorage, 1, 0); + h->data[0] = acquireFence; + acquireFenceHandle = h; + } - if (acquireFence >= 0) { - close(acquireFence); - } - - return data; -} - -FlexLayout Mapper::lockFlex(const native_handle_t* handle, - uint64_t producerUsageMask, - uint64_t consumerUsageMask, - const IMapper::Rect& accessRegion, - int acquireFence) { - NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1); - native_handle_t* acquireFenceHandle = nullptr; - if (acquireFence >= 0) { - acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1); - acquireFenceHandle->data[0] = acquireFence; - } - - FlexLayout layout = {}; - mMapper->lockFlex(handle, producerUsageMask, consumerUsageMask, accessRegion, - acquireFenceHandle, - [&](const auto& tmpError, const auto& tmpLayout) { + void* data = nullptr; + mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle, + [&](const auto& tmpError, const auto& tmpData) { ASSERT_EQ(Error::NONE, tmpError) - << "failed to lockFlex handle " << handle; - layout = tmpLayout; - }); + << "failed to lock buffer " << buffer; + data = tmpData; + }); - if (acquireFence >= 0) { - close(acquireFence); - } - - return layout; -} - -int Mapper::unlock(const native_handle_t* handle) { - int releaseFence = -1; - mMapper->unlock(handle, [&](const auto& tmpError, - const auto& tmpReleaseFence) { - ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock handle " << handle; - - auto handle = tmpReleaseFence.getNativeHandle(); - if (handle) { - ASSERT_EQ(0, handle->numInts) << "invalid fence handle " << handle; - if (handle->numFds == 1) { - releaseFence = dup(handle->data[0]); - ASSERT_LT(0, releaseFence) << "failed to dup fence fd"; - } else { - ASSERT_EQ(0, handle->numFds) << " invalid fence handle " << handle; - } + if (acquireFence >= 0) { + close(acquireFence); } - }); - return releaseFence; + return data; } -const native_handle_t* Mapper::allocate( - std::unique_ptr& allocatorClient, - const IAllocatorClient::BufferDescriptorInfo& info) { - BufferDescriptor descriptor = allocatorClient->createDescriptor(info); - if (::testing::Test::HasFatalFailure()) { - return nullptr; - } +YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, + uint64_t cpuUsage, + const IMapper::Rect& accessRegion, + int acquireFence) { + auto buffer = const_cast(bufferHandle); - Buffer buffer = allocatorClient->allocate(descriptor); - if (::testing::Test::HasFatalFailure()) { - allocatorClient->destroyDescriptor(descriptor); - return nullptr; - } + NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0); + hidl_handle acquireFenceHandle; + if (acquireFence >= 0) { + auto h = native_handle_init(acquireFenceStorage, 1, 0); + h->data[0] = acquireFence; + acquireFenceHandle = h; + } - const native_handle_t* handle = - allocatorClient->exportHandle(descriptor, buffer); - if (handle) { - retain(handle); - } + YCbCrLayout layout = {}; + mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle, + [&](const auto& tmpError, const auto& tmpLayout) { + ASSERT_EQ(Error::NONE, tmpError) + << "failed to lockYCbCr buffer " << buffer; + layout = tmpLayout; + }); - allocatorClient->free(buffer); - allocatorClient->destroyDescriptor(descriptor); + if (acquireFence >= 0) { + close(acquireFence); + } - return handle; + return layout; +} + +int Gralloc::unlock(const native_handle_t* bufferHandle) { + auto buffer = const_cast(bufferHandle); + + int releaseFence = -1; + mMapper->unlock( + buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " + << buffer; + + auto fenceHandle = tmpReleaseFence.getNativeHandle(); + if (fenceHandle) { + ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " + << fenceHandle; + if (fenceHandle->numFds == 1) { + releaseFence = dup(fenceHandle->data[0]); + ASSERT_LT(0, releaseFence) << "failed to dup fence fd"; + } else { + ASSERT_EQ(0, fenceHandle->numFds) + << " invalid fence handle " << fenceHandle; + } + } + }); + + return releaseFence; } } // namespace tests diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h index c186b00a54..757f20bcd2 100644 --- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h +++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h @@ -17,14 +17,12 @@ #ifndef VTS_HAL_GRAPHICS_MAPPER_UTILS #define VTS_HAL_GRAPHICS_MAPPER_UTILS -#include -#include +#include +#include #include #include -#include "VtsHalGraphicsAllocatorTestUtils.h" - namespace android { namespace hardware { namespace graphics { @@ -32,59 +30,62 @@ namespace mapper { namespace V2_0 { namespace tests { -using android::hardware::graphics::common::V1_0::PixelFormat; -using android::hardware::graphics::allocator::V2_0::IAllocatorClient; -using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient; +using android::hardware::graphics::allocator::V2_0::IAllocator; -// A wrapper to IMapper. -class Mapper { - public: - Mapper(); - ~Mapper(); +// A wrapper to IAllocator and IMapper. +class Gralloc { + public: + Gralloc(); + ~Gralloc(); - sp getRaw() const; + // IAllocator methods - void retain(const native_handle_t* handle); - void release(const native_handle_t* handle); + sp getAllocator() const; - struct Dimensions { - uint32_t width; - uint32_t height; - }; - Dimensions getDimensions(const native_handle_t* handle); + std::string dumpDebugInfo(); - PixelFormat getFormat(const native_handle_t* handle); - uint32_t getLayerCount(const native_handle_t* handle); - uint64_t getProducerUsageMask(const native_handle_t* handle); - uint64_t getConsumerUsageMask(const native_handle_t* handle); - BackingStore getBackingStore(const native_handle_t* handle); - uint32_t getStride(const native_handle_t* handle); + // When import is false, this simply calls IAllocator::allocate. When import + // is true, the returned buffers are also imported into the mapper. + // + // Either case, the returned buffers must be freed with freeBuffer. + std::vector allocate( + const BufferDescriptor& descriptor, uint32_t count, bool import = true, + uint32_t* outStride = nullptr); + const native_handle_t* allocate( + const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true, + uint32_t* outStride = nullptr); - // We use fd instead of hidl_handle in these functions to pass fences - // in and out of the mapper. The ownership of the fd is always transferred - // with each of these functions. - void* lock(const native_handle_t* handle, uint64_t producerUsageMask, - uint64_t consumerUsageMask, const IMapper::Rect& accessRegion, - int acquireFence); - FlexLayout lockFlex(const native_handle_t* handle, uint64_t producerUsageMask, - uint64_t consumerUsageMask, - const IMapper::Rect& accessRegion, int acquireFence); - int unlock(const native_handle_t* handle); + // IMapper methods - // Requests AllocatorClient to allocate a buffer, export the handle, and - // register the handle with mapper. - const native_handle_t* allocate( - std::unique_ptr& allocatorClient, - const IAllocatorClient::BufferDescriptorInfo& info); + sp getMapper() const; - private: - void init(); + BufferDescriptor createDescriptor( + const IMapper::BufferDescriptorInfo& descriptorInfo); - sp mMapper; + const native_handle_t* importBuffer(const hidl_handle& rawHandle); + void freeBuffer(const native_handle_t* bufferHandle); - // Keep track of all registered (retained) handles. When a test fails with - // ASSERT_*, the destructor will release the handles for the test. - std::unordered_map mHandles; + // We use fd instead of hidl_handle in these functions to pass fences + // in and out of the mapper. The ownership of the fd is always transferred + // with each of these functions. + void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, + const IMapper::Rect& accessRegion, int acquireFence); + YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, + uint64_t cpuUsage, const IMapper::Rect& accessRegion, + int acquireFence); + int unlock(const native_handle_t* bufferHandle); + + private: + void init(); + const native_handle_t* cloneBuffer(const hidl_handle& rawHandle); + + sp mAllocator; + sp mMapper; + + // Keep track of all cloned and imported handles. When a test fails with + // ASSERT_*, the destructor will free the handles for the test. + std::unordered_set mClonedBuffers; + std::unordered_set mImportedBuffers; }; } // namespace tests diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp index 92d74d5009..f066a1e2c5 100644 --- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp +++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp @@ -14,10 +14,10 @@ * limitations under the License. */ -#define LOG_TAG "graphics_mapper_hidl_hal_test" +#define LOG_TAG "VtsHalGraphicsMapperV2_0TargetTest" -#include #include +#include #include #include "VtsHalGraphicsMapperTestUtils.h" @@ -29,202 +29,384 @@ namespace V2_0 { namespace tests { namespace { -using namespace android::hardware::graphics::allocator::V2_0; -using namespace android::hardware::graphics::allocator::V2_0::tests; +using android::hardware::graphics::common::V1_0::BufferUsage; +using android::hardware::graphics::common::V1_0::PixelFormat; class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase { protected: void SetUp() override { - ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique()); - ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient()); - ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique()); + ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique()); - mDummyDescriptorInfo.width = 64; - mDummyDescriptorInfo.height = 64; - mDummyDescriptorInfo.layerCount = 1; - mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; - mDummyDescriptorInfo.producerUsageMask = - static_cast(ProducerUsage::CPU_WRITE); - mDummyDescriptorInfo.consumerUsageMask = - static_cast(ConsumerUsage::CPU_READ); + mDummyDescriptorInfo.width = 64; + mDummyDescriptorInfo.height = 64; + mDummyDescriptorInfo.layerCount = 1; + mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; + mDummyDescriptorInfo.usage = static_cast( + BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); } void TearDown() override {} - std::unique_ptr mAllocator; - std::unique_ptr mAllocatorClient; - std::unique_ptr mMapper; - IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{}; + std::unique_ptr mGralloc; + IMapper::BufferDescriptorInfo mDummyDescriptorInfo{}; }; /** - * Test IMapper::retain and IMapper::release. + * Test IAllocator::dumpDebugInfo by calling it. */ -TEST_F(GraphicsMapperHidlTest, RetainRelease) { - const native_handle_t* buffer; - ASSERT_NO_FATAL_FAILURE( - buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo)); - - const int maxRefs = 10; - for (int i = 0; i < maxRefs; i++) { - ASSERT_NO_FATAL_FAILURE(mMapper->retain(buffer)); - } - for (int i = 0; i < maxRefs; i++) { - ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer)); - } - - ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer)); +TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) { + mGralloc->dumpDebugInfo(); } /** - * Test IMapper::get* getters. + * Test IAllocator::allocate with valid buffer descriptors. */ -TEST_F(GraphicsMapperHidlTest, Getters) { - const native_handle_t* buffer; - ASSERT_NO_FATAL_FAILURE( - buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo)); +TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) { + BufferDescriptor descriptor; + ASSERT_NO_FATAL_FAILURE( + descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo)); - IAllocatorClient::BufferDescriptorInfo info = {}; + for (uint32_t count = 0; count < 5; count++) { + std::vector bufferHandles; + uint32_t stride; + ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate( + descriptor, count, false, &stride)); - Mapper::Dimensions dimensions; - ASSERT_NO_FATAL_FAILURE(dimensions = mMapper->getDimensions(buffer)); - info.width = dimensions.width; - info.height = dimensions.height; + if (count >= 1) { + EXPECT_LE(mDummyDescriptorInfo.width, stride) + << "invalid buffer stride"; + } - ASSERT_NO_FATAL_FAILURE(info.format = mMapper->getFormat(buffer)); - ASSERT_NO_FATAL_FAILURE(info.producerUsageMask = - mMapper->getProducerUsageMask(buffer)); - ASSERT_NO_FATAL_FAILURE(info.consumerUsageMask = - mMapper->getConsumerUsageMask(buffer)); + for (auto bufferHandle : bufferHandles) { + mGralloc->freeBuffer(bufferHandle); + } + } +} - EXPECT_EQ(mDummyDescriptorInfo.width, info.width); - EXPECT_EQ(mDummyDescriptorInfo.height, info.height); - EXPECT_EQ(mDummyDescriptorInfo.format, info.format); - EXPECT_EQ(mDummyDescriptorInfo.producerUsageMask, info.producerUsageMask); - EXPECT_EQ(mDummyDescriptorInfo.consumerUsageMask, info.consumerUsageMask); +/** + * Test IAllocator::allocate with invalid buffer descriptors. + */ +TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) { + // this assumes any valid descriptor is non-empty + BufferDescriptor descriptor; + mGralloc->getAllocator()->allocate( + descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) { + EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError); + }); +} - ASSERT_NO_FATAL_FAILURE(mMapper->getBackingStore(buffer)); +/** + * Test IAllocator::allocate does not leak. + */ +TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) { + auto info = mDummyDescriptorInfo; + info.width = 1024; + info.height = 1024; - uint32_t stride; - ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer)); - EXPECT_LE(info.width, stride); + for (int i = 0; i < 2048; i++) { + auto bufferHandle = mGralloc->allocate(info, false); + mGralloc->freeBuffer(bufferHandle); + } +} + +/** + * Test IMapper::createDescriptor with valid descriptor info. + */ +TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) { + ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo)); +} + +/** + * Test IMapper::createDescriptor with invalid descriptor info. + */ +TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) { + auto info = mDummyDescriptorInfo; + info.width = 0; + mGralloc->getMapper()->createDescriptor( + info, [&](const auto& tmpError, const auto&) { + EXPECT_EQ(Error::BAD_VALUE, tmpError) + << "createDescriptor did not fail with BAD_VALUE"; + }); +} + +/** + * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers. + */ +TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) { + const native_handle_t* bufferHandle; + ASSERT_NO_FATAL_FAILURE(bufferHandle = + mGralloc->allocate(mDummyDescriptorInfo, true)); + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle)); +} + +/** + * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers. + */ +TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) { + const native_handle_t* clonedBufferHandle; + ASSERT_NO_FATAL_FAILURE( + clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false)); + + // A cloned handle is a raw handle. Check that we can import it multiple + // times. + const native_handle_t* importedBufferHandles[2]; + ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] = + mGralloc->importBuffer(clonedBufferHandle)); + ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] = + mGralloc->importBuffer(clonedBufferHandle)); + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0])); + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1])); + + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle)); +} + +/** + * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances. + */ +TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) { + const native_handle_t* rawHandle; + ASSERT_NO_FATAL_FAILURE( + rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false)); + + native_handle_t* importedHandle = nullptr; + mGralloc->getMapper()->importBuffer( + rawHandle, [&](const auto& tmpError, const auto& buffer) { + ASSERT_EQ(Error::NONE, tmpError); + importedHandle = static_cast(buffer); + }); + + // free the imported handle with another mapper + std::unique_ptr anotherGralloc; + ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique()); + Error error = mGralloc->getMapper()->freeBuffer(importedHandle); + ASSERT_EQ(Error::NONE, error); + + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle)); +} + +/** + * Test IMapper::importBuffer and IMapper::freeBuffer do not leak. + */ +TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) { + auto info = mDummyDescriptorInfo; + info.width = 1024; + info.height = 1024; + + for (int i = 0; i < 2048; i++) { + auto bufferHandle = mGralloc->allocate(info, true); + mGralloc->freeBuffer(bufferHandle); + } +} + +/** + * Test IMapper::importBuffer with invalid buffers. + */ +TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) { + native_handle_t* invalidHandle = nullptr; + mGralloc->getMapper()->importBuffer( + invalidHandle, [&](const auto& tmpError, const auto&) { + EXPECT_EQ(Error::BAD_BUFFER, tmpError) + << "importBuffer with nullptr did not fail with BAD_BUFFER"; + }); + + invalidHandle = native_handle_create(0, 0); + mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, + const auto&) { + EXPECT_EQ(Error::BAD_BUFFER, tmpError) + << "importBuffer with invalid handle did not fail with BAD_BUFFER"; + }); + native_handle_delete(invalidHandle); + + const native_handle_t* importedHandle; + ASSERT_NO_FATAL_FAILURE(importedHandle = + mGralloc->allocate(mDummyDescriptorInfo, true)); + mGralloc->getMapper()->importBuffer( + importedHandle, [&](const auto& tmpError, const auto&) { + EXPECT_EQ(Error::BAD_BUFFER, tmpError) + << "importBuffer with an " + "already imported handle did " + "not fail with BAD_BUFFER"; + }); + mGralloc->freeBuffer(importedHandle); +} + +/** + * Test IMapper::freeBuffer with invalid buffers. + */ +TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) { + native_handle_t* invalidHandle = nullptr; + Error error = mGralloc->getMapper()->freeBuffer(invalidHandle); + EXPECT_EQ(Error::BAD_BUFFER, error) + << "freeBuffer with nullptr did not fail with BAD_BUFFER"; + + invalidHandle = native_handle_create(0, 0); + error = mGralloc->getMapper()->freeBuffer(invalidHandle); + EXPECT_EQ(Error::BAD_BUFFER, error) + << "freeBuffer with invalid handle did not fail with BAD_BUFFER"; + native_handle_delete(invalidHandle); + + const native_handle_t* clonedBufferHandle; + ASSERT_NO_FATAL_FAILURE( + clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false)); + error = mGralloc->getMapper()->freeBuffer(invalidHandle); + EXPECT_EQ(Error::BAD_BUFFER, error) + << "freeBuffer with un-imported handle did not fail with BAD_BUFFER"; + + mGralloc->freeBuffer(clonedBufferHandle); } /** * Test IMapper::lock and IMapper::unlock. */ -TEST_F(GraphicsMapperHidlTest, LockBasic) { - const auto& info = mDummyDescriptorInfo; +TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) { + const auto& info = mDummyDescriptorInfo; - const native_handle_t* buffer; - ASSERT_NO_FATAL_FAILURE( - buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo)); + const native_handle_t* bufferHandle; + uint32_t stride; + ASSERT_NO_FATAL_FAILURE(bufferHandle = + mGralloc->allocate(info, true, &stride)); - uint32_t stride; - ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer)); + // lock buffer for writing + const IMapper::Rect region{0, 0, static_cast(info.width), + static_cast(info.height)}; + int fence = -1; + uint8_t* data; + ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock( + bufferHandle, info.usage, region, fence))); - // lock buffer for writing - const IMapper::Rect region{0, 0, static_cast(info.width), - static_cast(info.height)}; - int fence = -1; - uint32_t* data; - ASSERT_NO_FATAL_FAILURE( - data = static_cast( - mMapper->lock(buffer, info.producerUsageMask, 0, region, fence))); + // RGBA_8888 + size_t strideInBytes = stride * 4; + size_t writeInBytes = info.width * 4; - for (uint32_t y = 0; y < info.height; y++) { - for (uint32_t x = 0; x < info.width; x++) { - data[stride * y + x] = info.height * y + x; + for (uint32_t y = 0; y < info.height; y++) { + memset(data, y, writeInBytes); + data += strideInBytes; } - } - ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer)); + ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle)); - // lock buffer for reading - ASSERT_NO_FATAL_FAILURE( - data = static_cast( - mMapper->lock(buffer, 0, info.consumerUsageMask, region, fence))); - for (uint32_t y = 0; y < info.height; y++) { - for (uint32_t x = 0; x < info.width; x++) { - EXPECT_EQ(info.height * y + x, data[stride * y + x]); + // lock again for reading + ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock( + bufferHandle, info.usage, region, fence))); + for (uint32_t y = 0; y < info.height; y++) { + for (size_t i = 0; i < writeInBytes; i++) { + EXPECT_EQ(static_cast(y), data[i]); + } + data += strideInBytes; } - } - ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer)); - if (fence >= 0) { - close(fence); - } + ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle)); + if (fence >= 0) { + close(fence); + } } /** - * Test IMapper::lockFlex. This locks a YV12 buffer, and makes sure we can + * Test IMapper::lockYCbCr. This locks a YV12 buffer, and makes sure we can * write to and read from it. */ -TEST_F(GraphicsMapperHidlTest, LockFlexBasic) { - auto info = mDummyDescriptorInfo; - info.format = PixelFormat::YV12; +TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) { + auto info = mDummyDescriptorInfo; + info.format = PixelFormat::YV12; - const native_handle_t* buffer; - ASSERT_NO_FATAL_FAILURE(buffer = mMapper->allocate(mAllocatorClient, info)); + const native_handle_t* bufferHandle; + uint32_t stride; + ASSERT_NO_FATAL_FAILURE(bufferHandle = + mGralloc->allocate(info, true, &stride)); - // lock buffer for writing - const IMapper::Rect region{0, 0, static_cast(info.width), - static_cast(info.height)}; - int fence = -1; - FlexLayout layout; - ASSERT_NO_FATAL_FAILURE( - layout = - mMapper->lockFlex(buffer, info.producerUsageMask, 0, region, fence)); - ASSERT_EQ(FlexFormat::YCBCR, layout.format); - ASSERT_EQ(3u, layout.planes.size()); + // lock buffer for writing + const IMapper::Rect region{0, 0, static_cast(info.width), + static_cast(info.height)}; + int fence = -1; + YCbCrLayout layout; + ASSERT_NO_FATAL_FAILURE( + layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence)); - const auto y_stride = layout.planes[0].vIncrement; - const auto c_stride = layout.planes[1].vIncrement; - auto y_data = static_cast(layout.planes[0].topLeft); - auto cb_data = static_cast(layout.planes[1].topLeft); - auto cr_data = static_cast(layout.planes[2].topLeft); + auto yData = static_cast(layout.y); + auto cbData = static_cast(layout.cb); + auto crData = static_cast(layout.cr); + for (uint32_t y = 0; y < info.height; y++) { + for (uint32_t x = 0; x < info.width; x++) { + auto val = static_cast(info.height * y + x); - for (uint32_t y = 0; y < info.height; y++) { - for (uint32_t x = 0; x < info.width; x++) { - auto val = static_cast(info.height * y + x); - - y_data[y_stride * y + x] = val; - if (y % 2 == 0 && x % 2 == 0) { - cb_data[c_stride * y / 2 + x / 2] = val; - cr_data[c_stride * y / 2 + x / 2] = val; - } + yData[layout.yStride * y + x] = val; + if (y % 2 == 0 && x % 2 == 0) { + cbData[layout.cStride * y / 2 + x / 2] = val; + crData[layout.cStride * y / 2 + x / 2] = val; + } + } } - } - ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer)); + ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle)); - // lock buffer for reading - ASSERT_NO_FATAL_FAILURE( - layout = - mMapper->lockFlex(buffer, 0, info.consumerUsageMask, region, fence)); + // lock again for reading + ASSERT_NO_FATAL_FAILURE( + layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence)); - y_data = static_cast(layout.planes[0].topLeft); - cb_data = static_cast(layout.planes[1].topLeft); - cr_data = static_cast(layout.planes[2].topLeft); - for (uint32_t y = 0; y < info.height; y++) { - for (uint32_t x = 0; x < info.width; x++) { - auto val = static_cast(info.height * y + x); + yData = static_cast(layout.y); + cbData = static_cast(layout.cb); + crData = static_cast(layout.cr); + for (uint32_t y = 0; y < info.height; y++) { + for (uint32_t x = 0; x < info.width; x++) { + auto val = static_cast(info.height * y + x); - EXPECT_EQ(val, y_data[y_stride * y + x]); - if (y % 2 == 0 && x % 2 == 0) { - EXPECT_EQ(val, cb_data[c_stride * y / 2 + x / 2]); - EXPECT_EQ(val, cr_data[c_stride * y / 2 + x / 2]); - } + EXPECT_EQ(val, yData[layout.yStride * y + x]); + if (y % 2 == 0 && x % 2 == 0) { + EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]); + EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]); + } + } } - } - ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer)); - if (fence >= 0) { - close(fence); - } + ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle)); + if (fence >= 0) { + close(fence); + } } -} // namespace anonymous +/** + * Test IMapper::unlock with invalid buffers. + */ +TEST_F(GraphicsMapperHidlTest, UnlockNegative) { + native_handle_t* invalidHandle = nullptr; + mGralloc->getMapper()->unlock( + invalidHandle, [&](const auto& tmpError, const auto&) { + EXPECT_EQ(Error::BAD_BUFFER, tmpError) + << "unlock with nullptr did not fail with BAD_BUFFER"; + }); + + invalidHandle = native_handle_create(0, 0); + mGralloc->getMapper()->unlock( + invalidHandle, [&](const auto& tmpError, const auto&) { + EXPECT_EQ(Error::BAD_BUFFER, tmpError) + << "unlock with invalid handle did not fail with BAD_BUFFER"; + }); + native_handle_delete(invalidHandle); + + ASSERT_NO_FATAL_FAILURE(invalidHandle = + const_cast(mGralloc->allocate( + mDummyDescriptorInfo, false))); + mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, + const auto&) { + EXPECT_EQ(Error::BAD_BUFFER, tmpError) + << "unlock with un-imported handle did not fail with BAD_BUFFER"; + }); + mGralloc->freeBuffer(invalidHandle); + +// disabled as it fails on many existing drivers +#if 0 + ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast( + mGralloc->allocate(mDummyDescriptorInfo, true))); + mGralloc->getMapper()->unlock( + invalidHandle, [&](const auto& tmpError, const auto&) { + EXPECT_EQ(Error::BAD_BUFFER, tmpError) + << "unlock with unlocked handle did not fail with BAD_BUFFER"; + }); + mGralloc->freeBuffer(invalidHandle); +#endif +} + +} // namespace } // namespace tests } // namespace V2_0 } // namespace mapper