diff options
author | 2016-10-21 15:23:44 -0700 | |
---|---|---|
committer | 2016-11-11 11:35:06 -0800 | |
commit | 6ebc46a7c01b22bc19d3c00b493f8d930b15b43a (patch) | |
tree | 6f68e8f1cf2ccde71eece4a037c8e32b4f0cd0b2 | |
parent | cd7dedbe69f8c90d351b97b1acea2bb3635b68ca (diff) |
Add layered buffer support to libui and libgui.
Bug: 31686534
Test: manual
Change-Id: Ia40270701467f4b785660324cad883e7da08989a
-rw-r--r-- | include/gui/GraphicBufferAlloc.h | 5 | ||||
-rw-r--r-- | include/gui/IGraphicBufferAlloc.h | 10 | ||||
-rw-r--r-- | include/ui/Gralloc1.h | 7 | ||||
-rw-r--r-- | include/ui/Gralloc1On0Adapter.h | 18 | ||||
-rw-r--r-- | include/ui/GrallocMapper.h | 5 | ||||
-rw-r--r-- | include/ui/GraphicBuffer.h | 16 | ||||
-rw-r--r-- | include/ui/GraphicBufferAllocator.h | 6 | ||||
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 22 | ||||
-rw-r--r-- | libs/gui/GraphicBufferAlloc.cpp | 12 | ||||
-rw-r--r-- | libs/gui/IGraphicBufferAlloc.cpp | 8 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 8 | ||||
-rw-r--r-- | libs/ui/Gralloc1.cpp | 20 | ||||
-rw-r--r-- | libs/ui/Gralloc1On0Adapter.cpp | 6 | ||||
-rw-r--r-- | libs/ui/GraphicBuffer.cpp | 92 | ||||
-rw-r--r-- | libs/ui/GraphicBufferAllocator.cpp | 51 | ||||
-rw-r--r-- | opengl/include/EGL/eglext.h | 1 | ||||
-rw-r--r-- | opengl/libs/EGL/eglApi.cpp | 17 | ||||
-rw-r--r-- | opengl/specs/EGL_ANDROID_create_native_client_buffer.txt | 15 |
18 files changed, 235 insertions, 84 deletions
diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h index 62e3877259..b19a1acc5e 100644 --- a/include/gui/GraphicBufferAlloc.h +++ b/include/gui/GraphicBufferAlloc.h @@ -34,8 +34,9 @@ public: GraphicBufferAlloc(); virtual ~GraphicBufferAlloc(); virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width, - uint32_t height, PixelFormat format, uint32_t usage, - std::string requestorName, status_t* error) override; + uint32_t height, PixelFormat format, uint32_t layerCount, + uint32_t usage, std::string requestorName, + status_t* error) override; }; diff --git a/include/gui/IGraphicBufferAlloc.h b/include/gui/IGraphicBufferAlloc.h index acc2f30bf4..2a7690a881 100644 --- a/include/gui/IGraphicBufferAlloc.h +++ b/include/gui/IGraphicBufferAlloc.h @@ -38,12 +38,14 @@ public: /* Create a new GraphicBuffer for the client to use. */ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, std::string requestorName, - status_t* error) = 0; + PixelFormat format, uint32_t layerCount, uint32_t usage, + std::string requestorName, status_t* error) = 0; sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error) { - return createGraphicBuffer(w, h, format, usage, "<Unknown>", error); + PixelFormat format, uint32_t layerCount, uint32_t usage, + status_t* error) { + return createGraphicBuffer(w, h, format, layerCount, usage, "<Unknown>", + error); } }; diff --git a/include/ui/Gralloc1.h b/include/ui/Gralloc1.h index cf8c173eee..64dacd7a99 100644 --- a/include/ui/Gralloc1.h +++ b/include/ui/Gralloc1.h @@ -49,6 +49,7 @@ public: mWidth(0), mHeight(0), mFormat(static_cast<android_pixel_format_t>(0)), + mLayerCount(0), mProducerUsage(GRALLOC1_PRODUCER_USAGE_NONE), mConsumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {} @@ -58,6 +59,7 @@ public: gralloc1_error_t setDimensions(uint32_t width, uint32_t height); gralloc1_error_t setFormat(android_pixel_format_t format); + gralloc1_error_t setLayerCount(uint32_t layerCount); gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage); gralloc1_error_t setConsumerUsage(gralloc1_consumer_usage_t usage); @@ -68,6 +70,7 @@ private: uint32_t mWidth; uint32_t mHeight; android_pixel_format_t mFormat; + uint32_t mLayerCount; gralloc1_producer_usage_t mProducerUsage; gralloc1_consumer_usage_t mConsumerUsage; @@ -178,6 +181,8 @@ private: GRALLOC1_FUNCTION_SET_DIMENSIONS> setDimensions; FunctionLoader<GRALLOC1_PFN_SET_FORMAT, GRALLOC1_FUNCTION_SET_FORMAT> setFormat; + FunctionLoader<GRALLOC1_PFN_SET_LAYER_COUNT, + GRALLOC1_FUNCTION_SET_LAYER_COUNT> setLayerCount; FunctionLoader<GRALLOC1_PFN_SET_PRODUCER_USAGE, GRALLOC1_FUNCTION_SET_PRODUCER_USAGE> setProducerUsage; FunctionLoader<GRALLOC1_PFN_GET_BACKING_STORE, @@ -188,6 +193,8 @@ private: GRALLOC1_FUNCTION_GET_DIMENSIONS> getDimensions; FunctionLoader<GRALLOC1_PFN_GET_FORMAT, GRALLOC1_FUNCTION_GET_FORMAT> getFormat; + FunctionLoader<GRALLOC1_PFN_GET_LAYER_COUNT, + GRALLOC1_FUNCTION_GET_LAYER_COUNT> getLayerCount; FunctionLoader<GRALLOC1_PFN_GET_PRODUCER_USAGE, GRALLOC1_FUNCTION_GET_PRODUCER_USAGE> getProducerUsage; FunctionLoader<GRALLOC1_PFN_GET_STRIDE, diff --git a/include/ui/Gralloc1On0Adapter.h b/include/ui/Gralloc1On0Adapter.h index d523c4f7e7..2508ce91bb 100644 --- a/include/ui/Gralloc1On0Adapter.h +++ b/include/ui/Gralloc1On0Adapter.h @@ -131,6 +131,7 @@ private: width(0), height(0), format(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), + layerCount(1), producerUsage(GRALLOC1_PRODUCER_USAGE_NONE), consumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {} @@ -145,6 +146,11 @@ private: return GRALLOC1_ERROR_NONE; } + gralloc1_error_t setLayerCount(uint32_t lc) { + layerCount = lc; + return GRALLOC1_ERROR_NONE; + } + gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage) { producerUsage = usage; return GRALLOC1_ERROR_NONE; @@ -161,6 +167,7 @@ private: uint32_t width; uint32_t height; int32_t format; + uint32_t layerCount; gralloc1_producer_usage_t producerUsage; gralloc1_consumer_usage_t consumerUsage; }; @@ -197,6 +204,12 @@ private: &Descriptor::setFormat, format); } + static int32_t setLayerCountHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, uint32_t layerCount) { + return callDescriptorFunction(device, descriptorId, + &Descriptor::setLayerCount, layerCount); + } + static int32_t setProducerUsageHook(gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) { auto usage = static_cast<gralloc1_producer_usage_t>(intUsage); @@ -246,6 +259,11 @@ private: return GRALLOC1_ERROR_NONE; } + gralloc1_error_t getLayerCount(uint32_t* outLayerCount) const { + *outLayerCount = mDescriptor.layerCount; + return GRALLOC1_ERROR_NONE; + } + gralloc1_error_t getNumFlexPlanes(uint32_t* outNumPlanes) const { // TODO: This is conservative, and we could do better by examining // the format, but it won't hurt anything for now diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h index 5517449241..868fd14430 100644 --- a/include/ui/GrallocMapper.h +++ b/include/ui/GrallocMapper.h @@ -63,6 +63,11 @@ public: return mMapper->getFormat(mDevice, handle, &format); } + Error getLayerCount(buffer_handle_t handle, uint32_t& layerCount) const + { + return mMapper->getLayerCount(mDevice, handle, &layerCount); + } + Error getProducerUsageMask(buffer_handle_t handle, uint64_t& usageMask) const { diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index 3e127a12a5..1bbcee2625 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -76,10 +76,15 @@ public: GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inUsage, std::string requestorName = "<Unknown>"); + // creates w * h buffer with a layer count + GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, + uint32_t inLayerCount, uint32_t inUsage, + std::string requestorName = "<Unknown>"); + // create a buffer from an existing handle GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, - uint32_t inUsage, uint32_t inStride, native_handle_t* inHandle, - bool keepOwnership); + uint32_t inLayerCount, uint32_t inUsage, uint32_t inStride, + native_handle_t* inHandle, bool keepOwnership); // create a buffer from an existing ANativeWindowBuffer GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership); @@ -92,6 +97,7 @@ public: uint32_t getStride() const { return static_cast<uint32_t>(stride); } uint32_t getUsage() const { return static_cast<uint32_t>(usage); } PixelFormat getPixelFormat() const { return format; } + uint32_t getLayerCount() const { return static_cast<uint32_t>(layerCount); } Rect getBounds() const { return Rect(width, height); } uint64_t getId() const { return mId; } @@ -101,10 +107,10 @@ public: } status_t reallocate(uint32_t inWidth, uint32_t inHeight, - PixelFormat inFormat, uint32_t inUsage); + PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage); bool needsReallocation(uint32_t inWidth, uint32_t inHeight, - PixelFormat inFormat, uint32_t inUsage); + PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage); status_t lock(uint32_t inUsage, void** vaddr); status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr); @@ -160,7 +166,7 @@ private: const GraphicBuffer& operator = (const GraphicBuffer& rhs) const; status_t initSize(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, - uint32_t inUsage, std::string requestorName); + uint32_t inLayerCount, uint32_t inUsage, std::string requestorName); void free_handle(); diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h index 9cc580696a..16967d430f 100644 --- a/include/ui/GraphicBufferAllocator.h +++ b/include/ui/GraphicBufferAllocator.h @@ -65,8 +65,9 @@ public: static inline GraphicBufferAllocator& get() { return getInstance(); } status_t allocate(uint32_t w, uint32_t h, PixelFormat format, - uint32_t usage, buffer_handle_t* handle, uint32_t* stride, - uint64_t graphicBufferId, std::string requestorName); + uint32_t layerCount, uint32_t usage, buffer_handle_t* handle, + uint32_t* stride, uint64_t graphicBufferId, + std::string requestorName); status_t free(buffer_handle_t handle); @@ -79,6 +80,7 @@ private: uint32_t height; uint32_t stride; PixelFormat format; + uint32_t layerCount; uint32_t usage; size_t size; std::string requestorName; diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 90b4b9df3d..9241c7c63d 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -42,6 +42,8 @@ namespace android { +static constexpr uint32_t BQ_LAYER_COUNT = 1; + BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger) : mCore(core), @@ -414,7 +416,8 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, // buffer. If this buffer would require reallocation to meet the // requested attributes, we free it and attempt to get another one. if (!mCore->mAllowAllocation) { - if (buffer->needsReallocation(width, height, format, usage)) { + if (buffer->needsReallocation(width, height, format, + BQ_LAYER_COUNT, usage)) { if (mCore->mSharedBufferSlot == found) { BQ_LOGE("dequeueBuffer: cannot re-allocate a shared" "buffer"); @@ -430,7 +433,8 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); if (mCore->mSharedBufferSlot == found && - buffer->needsReallocation(width, height, format, usage)) { + buffer->needsReallocation(width, height, format, + BQ_LAYER_COUNT, usage)) { BQ_LOGE("dequeueBuffer: cannot re-allocate a shared" "buffer"); @@ -449,7 +453,8 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, mSlots[found].mBufferState.dequeue(); if ((buffer == NULL) || - buffer->needsReallocation(width, height, format, usage)) + buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, + usage)) { mSlots[found].mAcquireCalled = false; mSlots[found].mGraphicBuffer = NULL; @@ -500,7 +505,7 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, status_t error; BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( - width, height, format, usage, + width, height, format, BQ_LAYER_COUNT, usage, {mConsumerName.string(), mConsumerName.size()}, &error)); { // Autolock scope Mutex::Autolock lock(mCore->mMutex); @@ -1039,6 +1044,10 @@ int BufferQueueProducer::query(int what, int *outValue) { case NATIVE_WINDOW_FORMAT: value = static_cast<int32_t>(mCore->mDefaultBufferFormat); break; + case NATIVE_WINDOW_LAYER_COUNT: + // All BufferQueue buffers have a single layer. + value = BQ_LAYER_COUNT; + break; case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: value = mCore->getMinUndequeuedBufferCountLocked(); break; @@ -1287,8 +1296,9 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, for (size_t i = 0; i < newBufferCount; ++i) { status_t result = NO_ERROR; sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( - allocWidth, allocHeight, allocFormat, allocUsage, - {mConsumerName.string(), mConsumerName.size()}, &result)); + allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT, + allocUsage, {mConsumerName.string(), mConsumerName.size()}, + &result)); if (result != NO_ERROR) { BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format" " %u, usage %u)", width, height, format, usage); diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp index e6150f4926..9d045dd44e 100644 --- a/libs/gui/GraphicBufferAlloc.cpp +++ b/libs/gui/GraphicBufferAlloc.cpp @@ -32,19 +32,21 @@ GraphicBufferAlloc::~GraphicBufferAlloc() { } sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width, - uint32_t height, PixelFormat format, uint32_t usage, - std::string requestorName, status_t* error) { + uint32_t height, PixelFormat format, uint32_t layerCount, + uint32_t usage, std::string requestorName, status_t* error) { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer( - width, height, format, usage, std::move(requestorName))); + width, height, format, layerCount, usage, + std::move(requestorName))); status_t err = graphicBuffer->initCheck(); *error = err; if (err != 0 || graphicBuffer->handle == 0) { if (err == NO_MEMORY) { GraphicBuffer::dumpAllocationsToSystemLog(); } - ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " + ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) " "failed (%s), handle=%p", - width, height, strerror(-err), graphicBuffer->handle); + width, height, layerCount, strerror(-err), + graphicBuffer->handle); return 0; } return graphicBuffer; diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp index 2fb380ccd1..a3d3b74c6b 100644 --- a/libs/gui/IGraphicBufferAlloc.cpp +++ b/libs/gui/IGraphicBufferAlloc.cpp @@ -45,13 +45,14 @@ public: virtual ~BpGraphicBufferAlloc(); virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width, - uint32_t height, PixelFormat format, uint32_t usage, - std::string requestorName, status_t* error) { + uint32_t height, PixelFormat format, uint32_t layerCount, + uint32_t usage, std::string requestorName, status_t* error) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor()); data.writeUint32(width); data.writeUint32(height); data.writeInt32(static_cast<int32_t>(format)); + data.writeUint32(layerCount); data.writeUint32(usage); if (requestorName.empty()) { requestorName += "[PID "; @@ -106,12 +107,13 @@ status_t BnGraphicBufferAlloc::onTransact( uint32_t width = data.readUint32(); uint32_t height = data.readUint32(); PixelFormat format = static_cast<PixelFormat>(data.readInt32()); + uint32_t layerCount = data.readUint32(); uint32_t usage = data.readUint32(); status_t error = NO_ERROR; std::string requestorName; data.readUtf8FromUtf16(&requestorName); sp<GraphicBuffer> result = createGraphicBuffer(width, height, - format, usage, requestorName, &error); + format, layerCount, usage, requestorName, &error); reply->writeInt32(error); if (result != 0) { reply->write(*result); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 0de60c983f..1aa03a526b 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -140,6 +140,14 @@ TEST_F(SurfaceTest, ConcreteTypeIsSurface) { EXPECT_EQ(NATIVE_WINDOW_SURFACE, result); } +TEST_F(SurfaceTest, LayerCountIsOne) { + sp<ANativeWindow> anw(mSurface); + int result = -123; + int err = anw->query(anw.get(), NATIVE_WINDOW_LAYER_COUNT, &result); + EXPECT_EQ(NO_ERROR, err); + EXPECT_EQ(1, result); +} + TEST_F(SurfaceTest, QueryConsumerUsage) { const int TEST_USAGE_FLAGS = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER; diff --git a/libs/ui/Gralloc1.cpp b/libs/ui/Gralloc1.cpp index 4c73ce4535..367d1ce58b 100644 --- a/libs/ui/Gralloc1.cpp +++ b/libs/ui/Gralloc1.cpp @@ -77,6 +77,17 @@ gralloc1_error_t Descriptor::setFormat(android_pixel_format_t format) mShimDevice.mDevice, mDeviceId, format, &mFormat); } +gralloc1_error_t Descriptor::setLayerCount(uint32_t layerCount) +{ + if (mShimDevice.hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) { + return setHelper<uint32_t>(mShimDevice.mFunctions.setLayerCount.pfn, + mShimDevice.mDevice, mDeviceId, layerCount, &mLayerCount); + } else { + // Layered buffers are not supported on this device. + return GRALLOC1_ERROR_UNSUPPORTED; + } +} + gralloc1_error_t Descriptor::setProducerUsage(gralloc1_producer_usage_t usage) { return setHelper<uint64_t>(mShimDevice.mFunctions.setProducerUsage.pfn, @@ -366,6 +377,15 @@ bool Device::loadFunctions() mFunctions.allocate.load(mDevice, false); } + if (hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) { + if (!mFunctions.setLayerCount.load(mDevice, true)) { + return false; + } + if (!mFunctions.getLayerCount.load(mDevice, true)) { + return false; + } + } + return true; } diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp index d5b88deb9a..111879aed1 100644 --- a/libs/ui/Gralloc1On0Adapter.cpp +++ b/libs/ui/Gralloc1On0Adapter.cpp @@ -97,6 +97,8 @@ gralloc1_function_pointer_t Gralloc1On0Adapter::doGetFunction( return asFP<GRALLOC1_PFN_SET_DIMENSIONS>(setDimensionsHook); case GRALLOC1_FUNCTION_SET_FORMAT: return asFP<GRALLOC1_PFN_SET_FORMAT>(setFormatHook); + case GRALLOC1_FUNCTION_SET_LAYER_COUNT: + return asFP<GRALLOC1_PFN_SET_LAYER_COUNT>(setLayerCountHook); case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE: return asFP<GRALLOC1_PFN_SET_PRODUCER_USAGE>(setProducerUsageHook); case GRALLOC1_FUNCTION_GET_BACKING_STORE: @@ -113,6 +115,10 @@ gralloc1_function_pointer_t Gralloc1On0Adapter::doGetFunction( return asFP<GRALLOC1_PFN_GET_FORMAT>( bufferHook<decltype(&Buffer::getFormat), &Buffer::getFormat, int32_t*>); + case GRALLOC1_FUNCTION_GET_LAYER_COUNT: + return asFP<GRALLOC1_PFN_GET_LAYER_COUNT>( + bufferHook<decltype(&Buffer::getLayerCount), + &Buffer::getLayerCount, uint32_t*>); case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE: return asFP<GRALLOC1_PFN_GET_PRODUCER_USAGE>(getProducerUsageHook); case GRALLOC1_FUNCTION_GET_STRIDE: diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 6d729006f7..07164a4f44 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -50,6 +50,7 @@ GraphicBuffer::GraphicBuffer() height = stride = format = + layerCount = usage = 0; handle = NULL; } @@ -63,15 +64,33 @@ GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, height = stride = format = + layerCount = usage = 0; handle = NULL; - mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage, + mInitCheck = initSize(inWidth, inHeight, inFormat, 1, inUsage, std::move(requestorName)); } GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, - PixelFormat inFormat, uint32_t inUsage, uint32_t inStride, - native_handle_t* inHandle, bool keepOwnership) + PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage, + std::string requestorName) + : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), + mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) +{ + width = + height = + stride = + format = + layerCount = + usage = 0; + handle = NULL; + mInitCheck = initSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, + std::move(requestorName)); +} + +GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, + PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage, + uint32_t inStride, native_handle_t* inHandle, bool keepOwnership) : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0) @@ -80,6 +99,7 @@ GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, height = static_cast<int>(inHeight); stride = static_cast<int>(inStride); format = inFormat; + layerCount = inLayerCount; usage = static_cast<int>(inUsage); handle = inHandle; } @@ -94,6 +114,7 @@ GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership) height = buffer->height; stride = buffer->stride; format = buffer->format; + layerCount = buffer->layerCount; usage = buffer->usage; handle = buffer->handle; } @@ -138,7 +159,7 @@ ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const } status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, - PixelFormat inFormat, uint32_t inUsage) + PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage) { if (mOwner != ownData) return INVALID_OPERATION; @@ -147,6 +168,7 @@ status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, static_cast<int>(inWidth) == width && static_cast<int>(inHeight) == height && inFormat == format && + inLayerCount == layerCount && static_cast<int>(inUsage) == usage) return NO_ERROR; @@ -155,30 +177,34 @@ status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight, allocator.free(handle); handle = 0; } - return initSize(inWidth, inHeight, inFormat, inUsage, "[Reallocation]"); + return initSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, + "[Reallocation]"); } bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight, - PixelFormat inFormat, uint32_t inUsage) + PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage) { if (static_cast<int>(inWidth) != width) return true; if (static_cast<int>(inHeight) != height) return true; if (inFormat != format) return true; + if (inLayerCount != layerCount) return true; if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true; return false; } status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight, - PixelFormat inFormat, uint32_t inUsage, std::string requestorName) + PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage, + std::string requestorName) { GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); uint32_t outStride = 0; - status_t err = allocator.allocate(inWidth, inHeight, inFormat, inUsage, - &handle, &outStride, mId, std::move(requestorName)); + status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount, + inUsage, &handle, &outStride, mId, std::move(requestorName)); if (err == NO_ERROR) { width = static_cast<int>(inWidth); height = static_cast<int>(inHeight); format = inFormat; + layerCount = inLayerCount; usage = static_cast<int>(inUsage); stride = static_cast<int>(outStride); } @@ -284,7 +310,7 @@ status_t GraphicBuffer::unlockAsync(int *fenceFd) } size_t GraphicBuffer::getFlattenedSize() const { - return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int); + return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int); } size_t GraphicBuffer::getFdCount() const { @@ -304,19 +330,20 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& buf[2] = height; buf[3] = stride; buf[4] = format; - buf[5] = usage; - buf[6] = static_cast<int32_t>(mId >> 32); - buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull); - buf[8] = static_cast<int32_t>(mGenerationNumber); - buf[9] = 0; + buf[5] = static_cast<int32_t>(layerCount); + buf[6] = usage; + buf[7] = static_cast<int32_t>(mId >> 32); + buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull); + buf[9] = static_cast<int32_t>(mGenerationNumber); buf[10] = 0; + buf[11] = 0; if (handle) { - buf[9] = handle->numFds; - buf[10] = handle->numInts; + buf[10] = handle->numFds; + buf[11] = handle->numInts; memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int)); - memcpy(&buf[11], handle->data + handle->numFds, + memcpy(&buf[12], handle->data + handle->numFds, static_cast<size_t>(handle->numInts) * sizeof(int)); } @@ -332,28 +359,28 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& status_t GraphicBuffer::unflatten( void const*& buffer, size_t& size, int const*& fds, size_t& count) { - if (size < 11 * sizeof(int)) return NO_MEMORY; + if (size < 12 * sizeof(int)) return NO_MEMORY; int const* buf = static_cast<int const*>(buffer); if (buf[0] != 'GBFR') return BAD_TYPE; - const size_t numFds = static_cast<size_t>(buf[9]); - const size_t numInts = static_cast<size_t>(buf[10]); + const size_t numFds = static_cast<size_t>(buf[10]); + const size_t numInts = static_cast<size_t>(buf[11]); // Limit the maxNumber to be relatively small. The number of fds or ints // should not come close to this number, and the number itself was simply // chosen to be high enough to not cause issues and low enough to prevent // overflow problems. const size_t maxNumber = 4096; - if (numFds >= maxNumber || numInts >= (maxNumber - 11)) { - width = height = stride = format = usage = 0; + if (numFds >= maxNumber || numInts >= (maxNumber - 12)) { + width = height = stride = format = layerCount = usage = 0; handle = NULL; ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts); return BAD_VALUE; } - const size_t sizeNeeded = (11 + numInts) * sizeof(int); + const size_t sizeNeeded = (12 + numInts) * sizeof(int); if (size < sizeNeeded) return NO_MEMORY; size_t fdCountNeeded = numFds; @@ -369,34 +396,35 @@ status_t GraphicBuffer::unflatten( height = buf[2]; stride = buf[3]; format = buf[4]; - usage = buf[5]; + layerCount = static_cast<uintptr_t>(buf[5]); + usage = buf[6]; native_handle* h = native_handle_create( static_cast<int>(numFds), static_cast<int>(numInts)); if (!h) { - width = height = stride = format = usage = 0; + width = height = stride = format = layerCount = usage = 0; handle = NULL; ALOGE("unflatten: native_handle_create failed"); return NO_MEMORY; } memcpy(h->data, fds, numFds * sizeof(int)); - memcpy(h->data + numFds, &buf[11], numInts * sizeof(int)); + memcpy(h->data + numFds, &buf[12], numInts * sizeof(int)); handle = h; } else { - width = height = stride = format = usage = 0; + width = height = stride = format = layerCount = usage = 0; handle = NULL; } - mId = static_cast<uint64_t>(buf[6]) << 32; - mId |= static_cast<uint32_t>(buf[7]); + mId = static_cast<uint64_t>(buf[7]) << 32; + mId |= static_cast<uint32_t>(buf[8]); - mGenerationNumber = static_cast<uint32_t>(buf[8]); + mGenerationNumber = static_cast<uint32_t>(buf[9]); mOwner = ownHandle; if (handle != 0) { status_t err = mBufferMapper.registerBuffer(this); if (err != NO_ERROR) { - width = height = stride = format = usage = 0; + width = height = stride = format = layerCount = usage = 0; handle = NULL; ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err); diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 693c7cbfab..e333bc10dd 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -64,15 +64,15 @@ void GraphicBufferAllocator::dump(String8& result) const for (size_t i=0 ; i<c ; i++) { const alloc_rec_t& rec(list.valueAt(i)); if (rec.size) { - snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x | %s\n", + snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%08x | %s\n", list.keyAt(i), rec.size/1024.0f, - rec.width, rec.stride, rec.height, rec.format, rec.usage, - rec.requestorName.c_str()); + rec.width, rec.stride, rec.height, rec.layerCount, rec.format, + rec.usage, rec.requestorName.c_str()); } else { - snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %8X | 0x%08x | %s\n", + snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %4u | %8X | 0x%08x | %s\n", list.keyAt(i), - rec.width, rec.stride, rec.height, rec.format, rec.usage, - rec.requestorName.c_str()); + rec.width, rec.stride, rec.height, rec.layerCount, rec.format, + rec.usage, rec.requestorName.c_str()); } result.append(buffer); total += rec.size; @@ -103,21 +103,22 @@ class HalBuffer { public: HalBuffer(const Gralloc2::Allocator* allocator, uint32_t width, uint32_t height, - PixelFormat format, uint32_t usage) + PixelFormat format, uint32_t layerCount, uint32_t usage) : mAllocator(allocator), mBufferValid(false) { Gralloc2::IAllocator::BufferDescriptorInfo info = {}; info.width = width; info.height = height; info.format = static_cast<Gralloc2::PixelFormat>(format); + info.layerCount = layerCount; info.producerUsageMask = usage; info.consumerUsageMask = usage; Gralloc2::BufferDescriptor descriptor; auto error = mAllocator->createBufferDescriptor(info, descriptor); if (error != Gralloc2::Error::NONE) { - ALOGE("Failed to create desc (%u x %u) format %d usage %u: %d", - width, height, format, usage, error); + ALOGE("Failed to create desc (%u x %u) layerCount %u format %d usage %u: %d", + width, height, layerCount, format, usage, error); return; } @@ -127,8 +128,8 @@ public: } if (error != Gralloc2::Error::NONE) { - ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d", - width, height, format, usage, error); + ALOGE("Failed to allocate (%u x %u) layerCount %u format %d usage %u: %d", + width, height, layerCount, format, usage, error); mAllocator->destroyBufferDescriptor(descriptor); return; } @@ -195,8 +196,9 @@ private: } // namespace status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, - PixelFormat format, uint32_t usage, buffer_handle_t* handle, - uint32_t* stride, uint64_t graphicBufferId, std::string requestorName) + PixelFormat format, uint32_t layerCount, uint32_t usage, + buffer_handle_t* handle, uint32_t* stride, uint64_t graphicBufferId, + std::string requestorName) { ATRACE_CALL(); @@ -205,12 +207,17 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, if (!width || !height) width = height = 1; + // Ensure that layerCount is valid. + if (layerCount < 1) + layerCount = 1; + // Filter out any usage bits that should not be passed to the gralloc module usage &= GRALLOC_USAGE_ALLOC_MASK; gralloc1_error_t error; if (mAllocator->valid()) { - HalBuffer buffer(mAllocator.get(), width, height, format, usage); + HalBuffer buffer(mAllocator.get(), width, height, format, layerCount, + usage); if (!buffer.exportHandle(mMapper, handle, stride)) { return NO_MEMORY; } @@ -229,6 +236,17 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, ALOGE("Failed to set format to %d: %d", format, error); return BAD_VALUE; } + if (mDevice->hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) { + error = descriptor->setLayerCount(layerCount); + if (error != GRALLOC1_ERROR_NONE) { + ALOGE("Failed to set layer count to %u: %d", layerCount, error); + return BAD_VALUE; + } + } else if (layerCount > 1) { + ALOGE("Failed to set layer count to %u: capability unsupported", + layerCount); + return BAD_VALUE; + } error = descriptor->setProducerUsage( static_cast<gralloc1_producer_usage_t>(usage)); if (error != GRALLOC1_ERROR_NONE) { @@ -244,8 +262,8 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, error = mDevice->allocate(descriptor, graphicBufferId, handle); if (error != GRALLOC1_ERROR_NONE) { - ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d", - width, height, format, usage, error); + ALOGE("Failed to allocate (%u x %u) layerCount %u format %d usage %u: %d", + width, height, layerCount, format, usage, error); return NO_MEMORY; } @@ -264,6 +282,7 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, rec.height = height; rec.stride = *stride; rec.format = format; + rec.layerCount = layerCount; rec.usage = usage; rec.size = static_cast<size_t>(height * (*stride) * bpp); rec.requestorName = std::move(requestorName); diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 8e69330968..7cb608e65a 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -607,6 +607,7 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROID) (EGLDisplay dpy, #ifndef EGL_ANDROID_create_native_client_buffer #define EGL_ANDROID_create_native_client_buffer 1 +#define EGL_LAYER_COUNT_ANDROID 0x3434 #define EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143 #define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001 #define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002 diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 3f2861f90e..0bfefd0b8d 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -1802,6 +1802,7 @@ EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list) uint32_t width = 0; uint32_t height = 0; uint32_t format = 0; + uint32_t layer_count = 1; uint32_t red_size = 0; uint32_t green_size = 0; uint32_t blue_size = 0; @@ -1827,6 +1828,7 @@ EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list) GET_NONNEGATIVE_VALUE(EGL_GREEN_SIZE, green_size); GET_NONNEGATIVE_VALUE(EGL_BLUE_SIZE, blue_size); GET_NONNEGATIVE_VALUE(EGL_ALPHA_SIZE, alpha_size); + GET_NONNEGATIVE_VALUE(EGL_LAYER_COUNT_ANDROID, layer_count); case EGL_NATIVE_BUFFER_USAGE_ANDROID: if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) { usage |= GRALLOC_USAGE_PROTECTED; @@ -1862,7 +1864,7 @@ EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list) alpha_size == 0) { format = HAL_PIXEL_FORMAT_RGB_565; } else { - ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }", + ALOGE("Invalid native pixel format { r=%u, g=%u, b=%u, a=%u }", red_size, green_size, blue_size, alpha_size); return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); } @@ -1907,7 +1909,9 @@ EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list) CHECK_ERROR_CONDITION("Unable to write height"); err = data.writeInt32(static_cast<int32_t>(format)); CHECK_ERROR_CONDITION("Unable to write format"); - err = data.writeUint32(usage); + err = data.writeUint32(layer_count); + CHECK_ERROR_CONDITION("Unable to write layer count"); + err = data.writeUint32(usage); CHECK_ERROR_CONDITION("Unable to write usage"); err = data.writeUtf8AsUtf16( std::string("[eglCreateNativeClientBufferANDROID pid ") + @@ -1924,12 +1928,13 @@ EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list) err = gBuffer->initCheck(); if (err != NO_ERROR) { - ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x", - width, height, format, usage, err); + ALOGE("Unable to create native buffer " + "{ w=%u, h=%u, f=%u, u=%#x, lc=%u}: %#x", width, height, format, + usage, layer_count, err); goto error_condition; } - ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }", - gBuffer, width, height, format, usage); + ALOGV("Created new native buffer %p { w=%u, h=%u, f=%u, u=%#x, lc=%u}", + gBuffer, width, height, format, usage, layer_count); return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer()); #undef CHECK_ERROR_CONDITION diff --git a/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt index a6fae80d7d..9b2bbbcb92 100644 --- a/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt +++ b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt @@ -20,7 +20,7 @@ Status Version - Version 1, January 19, 2016 + Version 1.1, October 26, 2016 Number @@ -53,6 +53,7 @@ EGLClientBuffer eglCreateNativeClientBufferANDROID( New Tokens + EGL_NATIVE_BUFFER_LAYER_COUNT_ANDROID 0x3434 EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143 EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001 EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002 @@ -103,6 +104,8 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) | EGL_ALPHA_SIZE | The bits of Alpha in | 0 | | | the color buffer | | | | buffer data | | + | EGL_LAYER_COUNT_ANDROID | The number of image | 1 | + | | layers in the buffer | | | EGL_NATIVE_BUFFER_USAGE_ANDROID | The usage bits of | 0 | | | the buffer data | | +---------------------------------+----------------------+---------------+ @@ -114,8 +117,10 @@ Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) EGL_RED_SIZE, EGL_GREEN_SIZE, and EGL_BLUE_SIZE must be non-zero and correspond to a valid pixel format for the implementation. If EGL_ALPHA_SIZE is non-zero then the combination of all four sizes must correspond to a - valid pixel format for the implementation. The - EGL_NATIVE_BUFFER_USAGE_ANDROID flag may include any of the following bits: + valid pixel format for the implementation. The value of + EGL_LAYER_COUNT_ANDROID must be a valid number of image layers for the + implementation. The EGL_NATIVE_BUFFER_USAGE_ANDROID flag may include any of + the following bits: EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID: Indicates that the created buffer must have a hardware-protected path to external display @@ -189,6 +194,10 @@ Issues Revision History +#3 (Craig Donner, October 26, 2016) + - Added EGL_LAYER_COUNT_ANDROID for creating buffers that back texture + arrays. + #2 (Craig Donner, April 15, 2016) - Set color formats and usage bits explicitly using additional attributes, and add value for new token EGL_NATIVE_BUFFER_USAGE_ANDROID. |