Add layered buffer support to libui and libgui.
Bug: 31686534
Test: manual
Change-Id: Ia40270701467f4b785660324cad883e7da08989a
diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h
index 62e3877..b19a1ac 100644
--- a/include/gui/GraphicBufferAlloc.h
+++ b/include/gui/GraphicBufferAlloc.h
@@ -34,8 +34,9 @@
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 acc2f30..2a7690a 100644
--- a/include/gui/IGraphicBufferAlloc.h
+++ b/include/gui/IGraphicBufferAlloc.h
@@ -38,12 +38,14 @@
/* 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 cf8c173..64dacd7 100644
--- a/include/ui/Gralloc1.h
+++ b/include/ui/Gralloc1.h
@@ -49,6 +49,7 @@
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 @@
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 @@
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 @@
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 @@
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 d523c4f..2508ce9 100644
--- a/include/ui/Gralloc1On0Adapter.h
+++ b/include/ui/Gralloc1On0Adapter.h
@@ -131,6 +131,7 @@
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 @@
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 @@
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 @@
&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 @@
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 5517449..868fd14 100644
--- a/include/ui/GrallocMapper.h
+++ b/include/ui/GrallocMapper.h
@@ -63,6 +63,11 @@
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 3e127a1..1bbcee2 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -76,10 +76,15 @@
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 @@
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 @@
}
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 @@
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 9cc5806..16967d4 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -65,8 +65,9 @@
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 @@
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 90b4b9d..9241c7c 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 @@
// 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 @@
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 @@
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 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 @@
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 @@
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 e6150f4..9d045dd 100644
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -32,19 +32,21 @@
}
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 2fb380c..a3d3b74 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -45,13 +45,14 @@
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 @@
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 0de60c9..1aa03a5 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -140,6 +140,14 @@
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 4c73ce4..367d1ce 100644
--- a/libs/ui/Gralloc1.cpp
+++ b/libs/ui/Gralloc1.cpp
@@ -77,6 +77,17 @@
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 @@
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 d5b88de..111879a 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -97,6 +97,8 @@
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 @@
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 6d72900..07164a4 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -50,6 +50,7 @@
height =
stride =
format =
+ layerCount =
usage = 0;
handle = NULL;
}
@@ -63,15 +64,33 @@
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 @@
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 @@
height = buffer->height;
stride = buffer->stride;
format = buffer->format;
+ layerCount = buffer->layerCount;
usage = buffer->usage;
handle = buffer->handle;
}
@@ -138,7 +159,7 @@
}
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 @@
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 @@
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 @@
}
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 @@
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::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 @@
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 693c7cb..e333bc1 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -64,15 +64,15 @@
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 @@
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 @@
}
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 @@
} // 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 @@
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 @@
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 @@
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 @@
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 8e69330..7cb608e 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -607,6 +607,7 @@
#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 3f2861f..0bfefd0 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -1802,6 +1802,7 @@
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 @@
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 @@
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 @@
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 @@
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 a6fae80..9b2bbbc 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 @@
Version
- Version 1, January 19, 2016
+ Version 1.1, October 26, 2016
Number
@@ -53,6 +53,7 @@
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 @@
| 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 @@
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 @@
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.