Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc56bf72 authored by Dan Stoza's avatar Dan Stoza Committed by Android (Google) Code Review
Browse files

Merge "BufferQueue: Add allocateBuffers method"

parents ff0d588d 29a3e908
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -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);
+13 −0
Original line number Original line Diff line number Diff line
@@ -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;
};
};


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
+10 −0
Original line number Original line Diff line number Diff line
@@ -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();


+55 −0
Original line number Original line Diff line number Diff line
@@ -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
+25 −0
Original line number Original line Diff line number Diff line
@@ -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);
}
}
Loading