diff options
Diffstat (limited to 'libs/ui/GraphicBuffer.cpp')
-rw-r--r-- | libs/ui/GraphicBuffer.cpp | 224 |
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 // --------------------------------------------------------------------------- |