summaryrefslogtreecommitdiff
path: root/libs/ui/GraphicBuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ui/GraphicBuffer.cpp')
-rw-r--r--libs/ui/GraphicBuffer.cpp224
1 files changed, 179 insertions, 45 deletions
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 4aa9f628ce..3fc6a2d34a 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "GraphicBuffer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <ui/GraphicBuffer.h>
@@ -22,10 +23,14 @@
#include <grallocusage/GrallocUsageConversion.h>
-#include <ui/DetachedBufferHandle.h>
+#ifndef LIBUI_IN_VNDK
+#include <ui/BufferHubBuffer.h>
+#endif // LIBUI_IN_VNDK
+
#include <ui/Gralloc2.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
+#include <utils/Trace.h>
namespace android {
@@ -44,6 +49,22 @@ sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {
return static_cast<GraphicBuffer *>(anwb);
}
+GraphicBuffer* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer* buffer) {
+ return reinterpret_cast<GraphicBuffer*>(buffer);
+}
+
+GraphicBuffer const* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer const* buffer) {
+ return reinterpret_cast<GraphicBuffer const*>(buffer);
+}
+
+AHardwareBuffer* GraphicBuffer::toAHardwareBuffer() {
+ return reinterpret_cast<AHardwareBuffer*>(this);
+}
+
+AHardwareBuffer const* GraphicBuffer::toAHardwareBuffer() const {
+ return reinterpret_cast<AHardwareBuffer const*>(this);
+}
+
GraphicBuffer::GraphicBuffer()
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
@@ -55,7 +76,7 @@ GraphicBuffer::GraphicBuffer()
usage_deprecated = 0;
usage = 0;
layerCount = 0;
- handle = NULL;
+ handle = nullptr;
}
// deprecated
@@ -90,11 +111,31 @@ GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod m
inUsage, inStride);
}
+#ifndef LIBUI_IN_VNDK
+GraphicBuffer::GraphicBuffer(std::unique_ptr<BufferHubBuffer> buffer) : GraphicBuffer() {
+ if (buffer == nullptr) {
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+
+ mInitCheck = initWithHandle(buffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
+ buffer->desc().width, buffer->desc().height,
+ static_cast<PixelFormat>(buffer->desc().format),
+ buffer->desc().layers, buffer->desc().usage, buffer->desc().stride);
+ mBufferId = buffer->id();
+ mBufferHubBuffer = std::move(buffer);
+}
+#endif // LIBUI_IN_VNDK
+
GraphicBuffer::~GraphicBuffer()
{
+ ATRACE_CALL();
if (handle) {
free_handle();
}
+ for (auto& [callback, context] : mDeathCallbacks) {
+ callback(context, mId);
+ }
}
void GraphicBuffer::free_handle()
@@ -105,7 +146,7 @@ void GraphicBuffer::free_handle()
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
}
- handle = NULL;
+ handle = nullptr;
}
status_t GraphicBuffer::initCheck() const {
@@ -140,7 +181,7 @@ status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
if (handle) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
- handle = 0;
+ handle = nullptr;
}
return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
}
@@ -153,6 +194,7 @@ bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
if (inFormat != format) return true;
if (inLayerCount != layerCount) return true;
if ((usage & inUsage) != inUsage) return true;
+ if ((usage & USAGE_PROTECTED) != (inUsage & USAGE_PROTECTED)) return true;
return false;
}
@@ -217,15 +259,15 @@ status_t GraphicBuffer::initWithHandle(const native_handle_t* inHandle, HandleWr
return NO_ERROR;
}
-status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
-{
+status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel,
+ int32_t* outBytesPerStride) {
const Rect lockBounds(width, height);
- status_t res = lock(inUsage, lockBounds, vaddr);
+ status_t res = lock(inUsage, lockBounds, vaddr, outBytesPerPixel, outBytesPerStride);
return res;
}
-status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
-{
+status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
if (rect.left < 0 || rect.right > width ||
rect.top < 0 || rect.bottom > height) {
ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
@@ -233,7 +275,10 @@ status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
width, height);
return BAD_VALUE;
}
- status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr);
+
+ status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr, outBytesPerPixel,
+ outBytesPerStride);
+
return res;
}
@@ -264,22 +309,22 @@ status_t GraphicBuffer::unlock()
return res;
}
-status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd)
-{
+status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
const Rect lockBounds(width, height);
- status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd);
+ status_t res =
+ lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
return res;
}
-status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,
- void** vaddr, int fenceFd)
-{
- return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd);
+status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
+ return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
}
-status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage,
- uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd)
-{
+status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
+ const Rect& rect, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
if (rect.left < 0 || rect.right > width ||
rect.top < 0 || rect.bottom > height) {
ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
@@ -287,8 +332,10 @@ status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage,
width, height);
return BAD_VALUE;
}
- status_t res = getBufferMapper().lockAsync(handle, inProducerUsage,
- inConsumerUsage, rect, vaddr, fenceFd);
+
+ status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, inConsumerUsage, rect,
+ vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
+
return res;
}
@@ -320,15 +367,37 @@ status_t GraphicBuffer::unlockAsync(int *fenceFd)
return res;
}
+status_t GraphicBuffer::isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage,
+ bool* outSupported) const {
+ return mBufferMapper.isSupported(inWidth, inHeight, inFormat, inLayerCount, inUsage,
+ outSupported);
+}
+
size_t GraphicBuffer::getFlattenedSize() const {
+#ifndef LIBUI_IN_VNDK
+ if (mBufferHubBuffer != nullptr) {
+ return 48;
+ }
+#endif
return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
}
size_t GraphicBuffer::getFdCount() const {
+#ifndef LIBUI_IN_VNDK
+ if (mBufferHubBuffer != nullptr) {
+ return 0;
+ }
+#endif
return static_cast<size_t>(handle ? mTransportNumFds : 0);
}
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
+#ifndef LIBUI_IN_VNDK
+ if (mBufferHubBuffer != nullptr) {
+ return flattenBufferHubBuffer(buffer, size);
+ }
+#endif
size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
if (size < sizeNeeded) return NO_MEMORY;
@@ -355,7 +424,7 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t&
buf[11] = int32_t(mTransportNumInts);
memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int));
memcpy(buf + 13, handle->data + handle->numFds,
- static_cast<size_t>(mTransportNumInts) * sizeof(int));
+ static_cast<size_t>(mTransportNumInts) * sizeof(int));
}
buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
@@ -364,14 +433,13 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t&
fds += mTransportNumFds;
count -= static_cast<size_t>(mTransportNumFds);
}
-
return NO_ERROR;
}
-status_t GraphicBuffer::unflatten(
- void const*& buffer, size_t& size, int const*& fds, size_t& count) {
- if (size < 12 * sizeof(int)) {
- android_errorWriteLog(0x534e4554, "114223584");
+status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& fds,
+ size_t& count) {
+ // Check if size is not smaller than buf[0] is supposed to take.
+ if (size < sizeof(int)) {
return NO_MEMORY;
}
@@ -386,10 +454,21 @@ status_t GraphicBuffer::unflatten(
} else if (buf[0] == 'GBFR') {
// old version, when usage bits were 32-bits
flattenWordCount = 12;
+ } else if (buf[0] == 'BHBB') { // BufferHub backed buffer.
+#ifndef LIBUI_IN_VNDK
+ return unflattenBufferHubBuffer(buffer, size);
+#else
+ return BAD_TYPE;
+#endif
} else {
return BAD_TYPE;
}
+ if (size < 12 * sizeof(int)) {
+ android_errorWriteLog(0x534e4554, "114223584");
+ return NO_MEMORY;
+ }
+
const size_t numFds = static_cast<size_t>(buf[10]);
const size_t numInts = static_cast<size_t>(buf[11]);
@@ -402,7 +481,7 @@ status_t GraphicBuffer::unflatten(
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
return BAD_VALUE;
}
@@ -430,13 +509,13 @@ status_t GraphicBuffer::unflatten(
} else {
usage = uint64_t(usage_deprecated);
}
- native_handle* h = native_handle_create(
- static_cast<int>(numFds), static_cast<int>(numInts));
+ native_handle* h =
+ native_handle_create(static_cast<int>(numFds), static_cast<int>(numInts));
if (!h) {
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
ALOGE("unflatten: native_handle_create failed");
return NO_MEMORY;
}
@@ -447,7 +526,7 @@ status_t GraphicBuffer::unflatten(
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
}
mId = static_cast<uint64_t>(buf[7]) << 32;
@@ -457,7 +536,7 @@ status_t GraphicBuffer::unflatten(
mOwner = ownHandle;
- if (handle != 0) {
+ if (handle != nullptr) {
buffer_handle_t importedHandle;
status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle);
@@ -465,7 +544,7 @@ status_t GraphicBuffer::unflatten(
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
return err;
}
@@ -480,27 +559,82 @@ status_t GraphicBuffer::unflatten(
size -= sizeNeeded;
fds += numFds;
count -= numFds;
-
return NO_ERROR;
}
-bool GraphicBuffer::isDetachedBuffer() const {
- return mDetachedBufferHandle && mDetachedBufferHandle->isValid();
+void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context) {
+ mDeathCallbacks.emplace_back(deathCallback, context);
+}
+
+#ifndef LIBUI_IN_VNDK
+status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size) const {
+ sp<NativeHandle> tokenHandle = mBufferHubBuffer->duplicate();
+ if (tokenHandle == nullptr || tokenHandle->handle() == nullptr ||
+ tokenHandle->handle()->numFds != 0) {
+ return BAD_VALUE;
+ }
+
+ // Size needed for one label, one number of ints inside the token, one generation number and
+ // the token itself.
+ int numIntsInToken = tokenHandle->handle()->numInts;
+ const size_t sizeNeeded = static_cast<size_t>(3 + numIntsInToken) * sizeof(int);
+ if (size < sizeNeeded) {
+ ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__,
+ static_cast<int>(sizeNeeded), static_cast<int>(size));
+ return NO_MEMORY;
+ }
+ size -= sizeNeeded;
+
+ int* buf = static_cast<int*>(buffer);
+ buf[0] = 'BHBB';
+ buf[1] = numIntsInToken;
+ memcpy(buf + 2, tokenHandle->handle()->data, static_cast<size_t>(numIntsInToken) * sizeof(int));
+ buf[2 + numIntsInToken] = static_cast<int32_t>(mGenerationNumber);
+
+ return NO_ERROR;
}
-status_t GraphicBuffer::setDetachedBufferHandle(std::unique_ptr<DetachedBufferHandle> channel) {
- if (isDetachedBuffer()) {
- ALOGW("setDetachedBuffer: there is already a BufferHub channel associated with this "
- "GraphicBuffer. Replacing the old one.");
+status_t GraphicBuffer::unflattenBufferHubBuffer(void const*& buffer, size_t& size) {
+ const int* buf = static_cast<const int*>(buffer);
+ int numIntsInToken = buf[1];
+ // Size needed for one label, one number of ints inside the token, one generation number and
+ // the token itself.
+ const size_t sizeNeeded = static_cast<size_t>(3 + numIntsInToken) * sizeof(int);
+ if (size < sizeNeeded) {
+ ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__,
+ static_cast<int>(sizeNeeded), static_cast<int>(size));
+ return NO_MEMORY;
+ }
+ size -= sizeNeeded;
+ native_handle_t* importToken = native_handle_create(/*numFds=*/0, /*numInts=*/numIntsInToken);
+ memcpy(importToken->data, buf + 2, static_cast<size_t>(buf[1]) * sizeof(int));
+ sp<NativeHandle> importTokenHandle = NativeHandle::create(importToken, /*ownHandle=*/true);
+ std::unique_ptr<BufferHubBuffer> bufferHubBuffer = BufferHubBuffer::import(importTokenHandle);
+ if (bufferHubBuffer == nullptr || bufferHubBuffer.get() == nullptr) {
+ return BAD_VALUE;
+ }
+ // Reconstruct this GraphicBuffer object using the new BufferHubBuffer object.
+ if (handle) {
+ free_handle();
}
+ mId = 0;
+ mGenerationNumber = static_cast<uint32_t>(buf[2 + numIntsInToken]);
+ mInitCheck =
+ initWithHandle(bufferHubBuffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
+ bufferHubBuffer->desc().width, bufferHubBuffer->desc().height,
+ static_cast<PixelFormat>(bufferHubBuffer->desc().format),
+ bufferHubBuffer->desc().layers, bufferHubBuffer->desc().usage,
+ bufferHubBuffer->desc().stride);
+ mBufferId = bufferHubBuffer->id();
+ mBufferHubBuffer.reset(std::move(bufferHubBuffer.get()));
- mDetachedBufferHandle = std::move(channel);
return NO_ERROR;
}
-std::unique_ptr<DetachedBufferHandle> GraphicBuffer::takeDetachedBufferHandle() {
- return std::move(mDetachedBufferHandle);
+bool GraphicBuffer::isBufferHubBuffer() const {
+ return mBufferHubBuffer != nullptr;
}
+#endif // LIBUI_IN_VNDK
// ---------------------------------------------------------------------------