Loading include/gui/BufferQueueProducer.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -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); Loading include/gui/IGraphicBufferProducer.h +13 −0 Original line number Original line Diff line number Diff line Loading @@ -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; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading include/gui/Surface.h +10 −0 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading libs/gui/BufferQueueProducer.cpp +55 −0 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 Loading libs/gui/IGraphicBufferProducer.cpp +25 −0 Original line number Original line Diff line number Diff line Loading @@ -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> Loading Loading @@ -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"); Loading Loading @@ -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); } } Loading Loading
include/gui/BufferQueueProducer.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -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); Loading
include/gui/IGraphicBufferProducer.h +13 −0 Original line number Original line Diff line number Diff line Loading @@ -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; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading
include/gui/Surface.h +10 −0 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading
libs/gui/BufferQueueProducer.cpp +55 −0 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 Loading
libs/gui/IGraphicBufferProducer.cpp +25 −0 Original line number Original line Diff line number Diff line Loading @@ -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> Loading Loading @@ -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"); Loading Loading @@ -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); } } Loading