Merge "BufferQueue: Add allocateBuffers method"
This commit is contained in:
commit
dc56bf721a
@ -169,6 +169,10 @@ public:
|
||||
// handle if any.
|
||||
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:
|
||||
// This is required by the IBinder::DeathRecipient interface
|
||||
virtual void binderDied(const wp<IBinder>& who);
|
||||
|
@ -429,6 +429,19 @@ public:
|
||||
// Passing NULL or a different stream handle will detach the previous
|
||||
// handle if any.
|
||||
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);
|
||||
|
||||
/* 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:
|
||||
virtual ~Surface();
|
||||
|
||||
|
@ -331,6 +331,7 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
|
||||
|
||||
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
|
||||
status_t error;
|
||||
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
|
||||
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
|
||||
width, height, format, usage, &error));
|
||||
if (graphicBuffer == NULL) {
|
||||
@ -852,6 +853,60 @@ status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream)
|
||||
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 */) {
|
||||
// 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
|
||||
|
@ -45,6 +45,7 @@ enum {
|
||||
CONNECT,
|
||||
DISCONNECT,
|
||||
SET_SIDEBAND_STREAM,
|
||||
ALLOCATE_BUFFERS,
|
||||
};
|
||||
|
||||
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
|
||||
@ -252,6 +253,21 @@ public:
|
||||
}
|
||||
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");
|
||||
@ -394,6 +410,15 @@ status_t BnGraphicBufferProducer::onTransact(
|
||||
reply->writeInt32(result);
|
||||
return NO_ERROR;
|
||||
} 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);
|
||||
}
|
||||
|
@ -91,6 +91,13 @@ void Surface::setSidebandStream(const sp<NativeHandle>& 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) {
|
||||
Surface* c = getSelf(window);
|
||||
return c->setSwapInterval(interval);
|
||||
|
@ -486,6 +486,12 @@ status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stre
|
||||
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(
|
||||
const QueueBufferOutput& qbo) {
|
||||
uint32_t w, h, transformHint, numPendingBuffers;
|
||||
|
@ -112,6 +112,8 @@ private:
|
||||
int api, bool producerControlledByApp, QueueBufferOutput* output);
|
||||
virtual status_t disconnect(int api);
|
||||
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
|
||||
|
@ -105,6 +105,11 @@ status_t MonitoredProducer::setSidebandStream(const sp<NativeHandle>& 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() {
|
||||
return mProducer->asBinder().get();
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
bool producerControlledByApp, QueueBufferOutput* output);
|
||||
virtual status_t disconnect(int api);
|
||||
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();
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user