Merge "BufferQueue: Add allocateBuffers method"
This commit is contained in:
commit
dc56bf721a
@ -169,6 +169,10 @@ public:
|
|||||||
// handle if any.
|
// handle if any.
|
||||||
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
|
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
|
||||||
|
|
||||||
|
// See IGraphicBufferProducer::allocateBuffers
|
||||||
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
||||||
|
uint32_t format, uint32_t usage);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is required by the IBinder::DeathRecipient interface
|
// This is required by the IBinder::DeathRecipient interface
|
||||||
virtual void binderDied(const wp<IBinder>& who);
|
virtual void binderDied(const wp<IBinder>& who);
|
||||||
|
@ -429,6 +429,19 @@ public:
|
|||||||
// Passing NULL or a different stream handle will detach the previous
|
// Passing NULL or a different stream handle will detach the previous
|
||||||
// handle if any.
|
// handle if any.
|
||||||
virtual status_t setSidebandStream(const sp<NativeHandle>& stream) = 0;
|
virtual status_t setSidebandStream(const sp<NativeHandle>& stream) = 0;
|
||||||
|
|
||||||
|
// Allocates buffers based on the given dimensions/format.
|
||||||
|
//
|
||||||
|
// This function will allocate up to the maximum number of buffers
|
||||||
|
// permitted by the current BufferQueue configuration. It will use the
|
||||||
|
// given format, dimensions, and usage bits, which are interpreted in the
|
||||||
|
// same way as for dequeueBuffer, and the async flag must be set the same
|
||||||
|
// way as for dequeueBuffer to ensure that the correct number of buffers are
|
||||||
|
// allocated. This is most useful to avoid an allocation delay during
|
||||||
|
// dequeueBuffer. If there are already the maximum number of buffers
|
||||||
|
// allocated, this function has no effect.
|
||||||
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
||||||
|
uint32_t format, uint32_t usage) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -91,6 +91,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setSidebandStream(const sp<NativeHandle>& stream);
|
void setSidebandStream(const sp<NativeHandle>& stream);
|
||||||
|
|
||||||
|
/* Allocates buffers based on the current dimensions/format.
|
||||||
|
*
|
||||||
|
* This function will allocate up to the maximum number of buffers
|
||||||
|
* permitted by the current BufferQueue configuration. It will use the
|
||||||
|
* default format and dimensions. This is most useful to avoid an allocation
|
||||||
|
* delay during dequeueBuffer. If there are already the maximum number of
|
||||||
|
* buffers allocated, this function has no effect.
|
||||||
|
*/
|
||||||
|
void allocateBuffers();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~Surface();
|
virtual ~Surface();
|
||||||
|
|
||||||
|
@ -331,6 +331,7 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
|
|||||||
|
|
||||||
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
|
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
|
||||||
status_t error;
|
status_t error;
|
||||||
|
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
|
||||||
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
|
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
|
||||||
width, height, format, usage, &error));
|
width, height, format, usage, &error));
|
||||||
if (graphicBuffer == NULL) {
|
if (graphicBuffer == NULL) {
|
||||||
@ -852,6 +853,60 @@ status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream)
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
|
||||||
|
uint32_t height, uint32_t format, uint32_t usage) {
|
||||||
|
Vector<int> freeSlots;
|
||||||
|
|
||||||
|
Mutex::Autolock lock(mCore->mMutex);
|
||||||
|
|
||||||
|
int currentBufferCount = 0;
|
||||||
|
for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
|
||||||
|
if (mSlots[slot].mGraphicBuffer != NULL) {
|
||||||
|
++currentBufferCount;
|
||||||
|
} else {
|
||||||
|
if (mSlots[slot].mBufferState != BufferSlot::FREE) {
|
||||||
|
BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
|
||||||
|
slot);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeSlots.push_front(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxBufferCount = mCore->getMaxBufferCountLocked(async);
|
||||||
|
BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
|
||||||
|
currentBufferCount, maxBufferCount);
|
||||||
|
for (; currentBufferCount < maxBufferCount; ++currentBufferCount) {
|
||||||
|
if (freeSlots.empty()) {
|
||||||
|
BQ_LOGE("allocateBuffers: ran out of free slots");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = width > 0 ? width : mCore->mDefaultWidth;
|
||||||
|
height = height > 0 ? height : mCore->mDefaultHeight;
|
||||||
|
format = format != 0 ? format : mCore->mDefaultBufferFormat;
|
||||||
|
usage |= mCore->mConsumerUsageBits;
|
||||||
|
|
||||||
|
status_t result = NO_ERROR;
|
||||||
|
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
|
||||||
|
width, height, format, usage, &result));
|
||||||
|
if (result != NO_ERROR) {
|
||||||
|
BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
|
||||||
|
" %u, usage %u)", width, height, format, usage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int slot = freeSlots[freeSlots.size() - 1];
|
||||||
|
mCore->freeBufferLocked(slot); // Clean up the slot first
|
||||||
|
mSlots[slot].mGraphicBuffer = graphicBuffer;
|
||||||
|
mSlots[slot].mFrameNumber = 0;
|
||||||
|
mSlots[slot].mFence = Fence::NO_FENCE;
|
||||||
|
BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
|
||||||
|
freeSlots.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
|
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
|
||||||
// If we're here, it means that a producer we were connected to died.
|
// If we're here, it means that a producer we were connected to died.
|
||||||
// We're guaranteed that we are still connected to it because we remove
|
// We're guaranteed that we are still connected to it because we remove
|
||||||
|
@ -45,6 +45,7 @@ enum {
|
|||||||
CONNECT,
|
CONNECT,
|
||||||
DISCONNECT,
|
DISCONNECT,
|
||||||
SET_SIDEBAND_STREAM,
|
SET_SIDEBAND_STREAM,
|
||||||
|
ALLOCATE_BUFFERS,
|
||||||
};
|
};
|
||||||
|
|
||||||
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
|
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
|
||||||
@ -252,6 +253,21 @@ public:
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
||||||
|
uint32_t format, uint32_t usage) {
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
|
||||||
|
data.writeInt32(static_cast<int32_t>(async));
|
||||||
|
data.writeInt32(static_cast<int32_t>(width));
|
||||||
|
data.writeInt32(static_cast<int32_t>(height));
|
||||||
|
data.writeInt32(static_cast<int32_t>(format));
|
||||||
|
data.writeInt32(static_cast<int32_t>(usage));
|
||||||
|
status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
|
||||||
|
if (result != NO_ERROR) {
|
||||||
|
ALOGE("allocateBuffers failed to transact: %d", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
|
IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
|
||||||
@ -394,6 +410,15 @@ status_t BnGraphicBufferProducer::onTransact(
|
|||||||
reply->writeInt32(result);
|
reply->writeInt32(result);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
} break;
|
} break;
|
||||||
|
case ALLOCATE_BUFFERS:
|
||||||
|
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
|
||||||
|
bool async = static_cast<bool>(data.readInt32());
|
||||||
|
uint32_t width = static_cast<uint32_t>(data.readInt32());
|
||||||
|
uint32_t height = static_cast<uint32_t>(data.readInt32());
|
||||||
|
uint32_t format = static_cast<uint32_t>(data.readInt32());
|
||||||
|
uint32_t usage = static_cast<uint32_t>(data.readInt32());
|
||||||
|
allocateBuffers(async, width, height, format, usage);
|
||||||
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
return BBinder::onTransact(code, data, reply, flags);
|
return BBinder::onTransact(code, data, reply, flags);
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,13 @@ void Surface::setSidebandStream(const sp<NativeHandle>& stream) {
|
|||||||
mGraphicBufferProducer->setSidebandStream(stream);
|
mGraphicBufferProducer->setSidebandStream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Surface::allocateBuffers() {
|
||||||
|
uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
|
||||||
|
uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
|
||||||
|
mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, mReqWidth,
|
||||||
|
mReqHeight, mReqFormat, mReqUsage);
|
||||||
|
}
|
||||||
|
|
||||||
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
|
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
|
||||||
Surface* c = getSelf(window);
|
Surface* c = getSelf(window);
|
||||||
return c->setSwapInterval(interval);
|
return c->setSwapInterval(interval);
|
||||||
|
@ -486,6 +486,12 @@ status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stre
|
|||||||
return INVALID_OPERATION;
|
return INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VirtualDisplaySurface::allocateBuffers(bool /* async */,
|
||||||
|
uint32_t /* width */, uint32_t /* height */, uint32_t /* format */,
|
||||||
|
uint32_t /* usage */) {
|
||||||
|
// TODO: Should we actually allocate buffers for a virtual display?
|
||||||
|
}
|
||||||
|
|
||||||
void VirtualDisplaySurface::updateQueueBufferOutput(
|
void VirtualDisplaySurface::updateQueueBufferOutput(
|
||||||
const QueueBufferOutput& qbo) {
|
const QueueBufferOutput& qbo) {
|
||||||
uint32_t w, h, transformHint, numPendingBuffers;
|
uint32_t w, h, transformHint, numPendingBuffers;
|
||||||
|
@ -112,6 +112,8 @@ private:
|
|||||||
int api, bool producerControlledByApp, QueueBufferOutput* output);
|
int api, bool producerControlledByApp, QueueBufferOutput* output);
|
||||||
virtual status_t disconnect(int api);
|
virtual status_t disconnect(int api);
|
||||||
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
|
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
|
||||||
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
||||||
|
uint32_t format, uint32_t usage);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Utility methods
|
// Utility methods
|
||||||
|
@ -105,6 +105,11 @@ status_t MonitoredProducer::setSidebandStream(const sp<NativeHandle>& stream) {
|
|||||||
return mProducer->setSidebandStream(stream);
|
return mProducer->setSidebandStream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MonitoredProducer::allocateBuffers(bool async, uint32_t width,
|
||||||
|
uint32_t height, uint32_t format, uint32_t usage) {
|
||||||
|
mProducer->allocateBuffers(async, width, height, format, usage);
|
||||||
|
}
|
||||||
|
|
||||||
IBinder* MonitoredProducer::onAsBinder() {
|
IBinder* MonitoredProducer::onAsBinder() {
|
||||||
return mProducer->asBinder().get();
|
return mProducer->asBinder().get();
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,8 @@ public:
|
|||||||
bool producerControlledByApp, QueueBufferOutput* output);
|
bool producerControlledByApp, QueueBufferOutput* output);
|
||||||
virtual status_t disconnect(int api);
|
virtual status_t disconnect(int api);
|
||||||
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
|
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
|
||||||
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
||||||
|
uint32_t format, uint32_t usage);
|
||||||
virtual IBinder* onAsBinder();
|
virtual IBinder* onAsBinder();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user