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<handle> 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<uint32_t> 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
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 1dc5aea..090c61f 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -18,10 +18,9 @@
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 @@
"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 0000000..28f5016
--- /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 <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
+ : mModule(reinterpret_cast<const gralloc_module_t*>(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 0000000..e792a69
--- /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 <hardware/gralloc.h>
+
+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 0000000..c1e5adc
--- /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 <vector>
+
+#include <log/log.h>
+
+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<int32_t> 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 <typename T>
+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<T>(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<uint64_t>(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<android_flex_plane_t> 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<uint64_t>(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 0000000..452afdf
--- /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 <hardware/gralloc1.h>
+
+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 <typename T>
+ 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 0000000..9b5ab04
--- /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 <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+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<uint32_t>(descriptorInfo.format);
+ descriptor[5] = static_cast<uint32_t>(descriptorInfo.usage);
+ descriptor[6] = static_cast<uint32_t>(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<PixelFormat>(descriptor[4]),
+ (static_cast<uint64_t>(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 526aca2..339317a 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 <mutex>
-#include <vector>
-#include <unordered_map>
+#include "Gralloc0Mapper.h"
+#include "Gralloc1Mapper.h"
+#include "GrallocBufferDescriptor.h"
-#include <string.h>
+#include <inttypes.h>
-#include <hardware/gralloc1.h>
#include <log/log.h>
+#include <sync/sync.h>
namespace android {
namespace hardware {
@@ -33,374 +33,251 @@
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<buffer_handle_t> GrallocMapper::mRegisteredHandles;
- // IMapper interface
- Return<Error> retain(const hidl_handle& bufferHandle) override;
- Return<Error> release(const hidl_handle& bufferHandle) override;
- Return<void> getDimensions(const hidl_handle& bufferHandle,
- getDimensions_cb hidl_cb) override;
- Return<void> getFormat(const hidl_handle& bufferHandle,
- getFormat_cb hidl_cb) override;
- Return<void> getLayerCount(const hidl_handle& bufferHandle,
- getLayerCount_cb hidl_cb) override;
- Return<void> getProducerUsageMask(const hidl_handle& bufferHandle,
- getProducerUsageMask_cb hidl_cb) override;
- Return<void> getConsumerUsageMask(const hidl_handle& bufferHandle,
- getConsumerUsageMask_cb hidl_cb) override;
- Return<void> getBackingStore(const hidl_handle& bufferHandle,
- getBackingStore_cb hidl_cb) override;
- Return<void> getStride(const hidl_handle& bufferHandle,
- getStride_cb hidl_cb) override;
- Return<void> 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<void> 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<void> 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<BufferUsage>(0));
-private:
- void initCapabilities();
-
- template<typename T>
- 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<buffer_handle_t, size_t> 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<int32_t> 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<typename T>
-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<T>(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<Error> 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<std::mutex> lock(mMutex);
-
- ++mBufferReferenceCounts[nativeHandle];
- }
- return static_cast<Error>(err);
-}
-
-Return<Error> 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<std::mutex> 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<native_handle_t*>(nativeHandle));
-
- mBufferReferenceCounts.erase(iter);
- }
+ if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
+ return false;
}
- return static_cast<Error>(err);
-}
-
-Return<void> 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<Error>(err), width, height);
- return Void();
-}
-
-Return<void> 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<Error>(err), static_cast<PixelFormat>(format));
- return Void();
-}
-
-Return<void> 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<PixelFormat>(0)) {
+ return false;
}
- hidl_cb(static_cast<Error>(err), count);
+ 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<void> 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());
+ }
+
return Void();
}
-Return<void> 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<Error>(err), mask);
- return Void();
+bool GrallocMapper::addRegisteredHandle(buffer_handle_t bufferHandle) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.insert(bufferHandle).second;
}
-Return<void> 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<native_handle_t*>(buffer);
- hidl_cb(static_cast<Error>(err), mask);
- return Void();
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
}
-Return<void> 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_handle_t>(buffer);
- hidl_cb(static_cast<Error>(err), store);
- return Void();
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
}
-Return<void> GrallocMapperHal::getStride(const hidl_handle& bufferHandle,
- getStride_cb hidl_cb)
-{
- uint32_t stride = 0;
- int32_t err = mDispatch.getStride(mDevice, bufferHandle, &stride);
+Return<void> 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<Error>(err), stride);
- return Void();
-}
+ if (!rawHandle.getNativeHandle()) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
-Return<void> 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<Error> 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<void> 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<Error>(err), data);
+ hidl_cb(error, data);
return Void();
}
-Return<void> 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<void> 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<Error>(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<android_flex_plane_t> 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<FlexFormat>(layout.format);
+ hidl_cb(error, layout);
+ return Void();
+}
- planes.resize(layout.num_planes);
- layout_reply.planes.setToExternal(
- reinterpret_cast<FlexPlane*>(planes.data()), planes.size());
+Return<void> 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<Error>(err), layout_reply);
return Void();
}
-Return<void> 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<Error>(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 @@
}
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 a2f89d1..c9c6d8a 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 <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+
+#include <mutex>
+#include <unordered_set>
namespace android {
namespace hardware {
@@ -26,6 +30,68 @@
namespace V2_0 {
namespace implementation {
+class GrallocMapper : public IMapper {
+ public:
+ // IMapper interface
+ Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
+ createDescriptor_cb hidl_cb) override;
+ Return<void> importBuffer(const hidl_handle& rawHandle,
+ importBuffer_cb hidl_cb) override;
+ Return<Error> freeBuffer(void* buffer) override;
+ Return<void> lock(void* buffer, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lock_cb hidl_cb) override;
+ Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lockYCbCr_cb hidl_cb) override;
+ Return<void> 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<buffer_handle_t> mRegisteredHandles;
+};
+
extern "C" IMapper* HIDL_FETCH_IMapper(const char* name);
} // namespace implementation