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

Commit 0297dcae authored by Mathias Agopian's avatar Mathias Agopian
Browse files

Fix a bug where setgeometry couldn't be undone

This change the binder protocol between SurfaceTextureClient
and SurfaceTexture. dequeueBuffer() now takes the requested
parameters for the buffer. SurfaceTexture decides if the
buffer needs to be reallocated and does the allocation
if needed. In that case it returns BUFFER_NEEDS_REALLOCATION
to tell SurfaceTextureClient that it needs to call
requestBuffer (which all parameters have been removed) to
acquire a pointer to the buffer.

dequeueBuffer and requestBuffer could be folded into a single
IPC call, but we chose to optimize the case where buffers are
not created and avoid some complexity in the marshalling code.

Change-Id: I097a7f6f40a3491e10f3f3742eab33999286c304
parent f605a5aa
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -43,8 +43,7 @@ public:
    // the given slot index, and the client is expected to mirror the
    // the given slot index, and the client is expected to mirror the
    // slot->buffer mapping so that it's not necessary to transfer a
    // slot->buffer mapping so that it's not necessary to transfer a
    // GraphicBuffer for every dequeue operation.
    // GraphicBuffer for every dequeue operation.
    virtual sp<GraphicBuffer> requestBuffer(int slot, uint32_t w, uint32_t h,
    virtual sp<GraphicBuffer> requestBuffer(int slot) = 0;
            uint32_t format, uint32_t usage) = 0;


    // setBufferCount sets the number of buffer slots available. Calling this
    // setBufferCount sets the number of buffer slots available. Calling this
    // will also cause all buffer slots to be emptied. The caller should empty
    // will also cause all buffer slots to be emptied. The caller should empty
@@ -60,7 +59,8 @@ public:
    // in the contents of its associated buffer contents and call queueBuffer.
    // in the contents of its associated buffer contents and call queueBuffer.
    // If dequeueBuffer return BUFFER_NEEDS_REALLOCATION, the client is
    // If dequeueBuffer return BUFFER_NEEDS_REALLOCATION, the client is
    // expected to call requestBuffer immediately.
    // expected to call requestBuffer immediately.
    virtual status_t dequeueBuffer(int *slot) = 0;
    virtual status_t dequeueBuffer(int *slot, uint32_t w, uint32_t h,
            uint32_t format, uint32_t usage) = 0;


    // queueBuffer indicates that the client has finished filling in the
    // queueBuffer indicates that the client has finished filling in the
    // contents of the buffer associated with slot and transfers ownership of
    // contents of the buffer associated with slot and transfers ownership of
+3 −8
Original line number Original line Diff line number Diff line
@@ -56,15 +56,15 @@ public:
    // SurfaceTexture object (i.e. they are not owned by the client).
    // SurfaceTexture object (i.e. they are not owned by the client).
    virtual status_t setBufferCount(int bufferCount);
    virtual status_t setBufferCount(int bufferCount);


    virtual sp<GraphicBuffer> requestBuffer(int buf, uint32_t w, uint32_t h,
    virtual sp<GraphicBuffer> requestBuffer(int buf);
            uint32_t format, uint32_t usage);


    // dequeueBuffer gets the next buffer slot index for the client to use. If a
    // dequeueBuffer gets the next buffer slot index for the client to use. If a
    // buffer slot is available then that slot index is written to the location
    // buffer slot is available then that slot index is written to the location
    // pointed to by the buf argument and a status of OK is returned.  If no
    // pointed to by the buf argument and a status of OK is returned.  If no
    // slot is available then a status of -EBUSY is returned and buf is
    // slot is available then a status of -EBUSY is returned and buf is
    // unmodified.
    // unmodified.
    virtual status_t dequeueBuffer(int *buf);
    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
            uint32_t format, uint32_t usage);


    // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
    // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
    // timestamp must be provided for the buffer. The timestamp is in
    // timestamp must be provided for the buffer. The timestamp is in
@@ -193,11 +193,6 @@ private:
    // in requestBuffers() if a format of zero is specified.
    // in requestBuffers() if a format of zero is specified.
    uint32_t mPixelFormat;
    uint32_t mPixelFormat;


    // mUseDefaultSize indicates whether or not the default size should be used
    // that is, if the last requestBuffer has been called with both width
    // and height null.
    bool mUseDefaultSize;

    // mBufferCount is the number of buffer slots that the client and server
    // mBufferCount is the number of buffer slots that the client and server
    // must maintain. It defaults to MIN_BUFFER_SLOTS and can be changed by
    // must maintain. It defaults to MIN_BUFFER_SLOTS and can be changed by
    // calling setBufferCount.
    // calling setBufferCount.
+13 −14
Original line number Original line Diff line number Diff line
@@ -50,15 +50,10 @@ public:
    {
    {
    }
    }


    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
        Parcel data, reply;
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
        data.writeInt32(bufferIdx);
        data.writeInt32(bufferIdx);
        data.writeInt32(w);
        data.writeInt32(h);
        data.writeInt32(format);
        data.writeInt32(usage);
        remote()->transact(REQUEST_BUFFER, data, &reply);
        remote()->transact(REQUEST_BUFFER, data, &reply);
        sp<GraphicBuffer> buffer;
        sp<GraphicBuffer> buffer;
        bool nonNull = reply.readInt32();
        bool nonNull = reply.readInt32();
@@ -79,9 +74,14 @@ public:
        return err;
        return err;
    }
    }


    virtual status_t dequeueBuffer(int *buf) {
    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
            uint32_t format, uint32_t usage) {
        Parcel data, reply;
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
        data.writeInt32(w);
        data.writeInt32(h);
        data.writeInt32(format);
        data.writeInt32(usage);
        remote()->transact(DEQUEUE_BUFFER, data, &reply);
        remote()->transact(DEQUEUE_BUFFER, data, &reply);
        *buf = reply.readInt32();
        *buf = reply.readInt32();
        int result = reply.readInt32();
        int result = reply.readInt32();
@@ -145,12 +145,7 @@ status_t BnSurfaceTexture::onTransact(
        case REQUEST_BUFFER: {
        case REQUEST_BUFFER: {
            CHECK_INTERFACE(ISurfaceTexture, data, reply);
            CHECK_INTERFACE(ISurfaceTexture, data, reply);
            int bufferIdx   = data.readInt32();
            int bufferIdx   = data.readInt32();
            uint32_t w      = data.readInt32();
            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
            uint32_t h      = data.readInt32();
            uint32_t format = data.readInt32();
            uint32_t usage  = data.readInt32();
            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format,
                    usage));
            reply->writeInt32(buffer != 0);
            reply->writeInt32(buffer != 0);
            if (buffer != 0) {
            if (buffer != 0) {
                reply->write(*buffer);
                reply->write(*buffer);
@@ -166,8 +161,12 @@ status_t BnSurfaceTexture::onTransact(
        } break;
        } break;
        case DEQUEUE_BUFFER: {
        case DEQUEUE_BUFFER: {
            CHECK_INTERFACE(ISurfaceTexture, data, reply);
            CHECK_INTERFACE(ISurfaceTexture, data, reply);
            uint32_t w      = data.readInt32();
            uint32_t h      = data.readInt32();
            uint32_t format = data.readInt32();
            uint32_t usage  = data.readInt32();
            int buf;
            int buf;
            int result = dequeueBuffer(&buf);
            int result = dequeueBuffer(&buf, w, h, format, usage);
            reply->writeInt32(buf);
            reply->writeInt32(buf);
            reply->writeInt32(result);
            reply->writeInt32(result);
            return NO_ERROR;
            return NO_ERROR;
+40 −41
Original line number Original line Diff line number Diff line
@@ -81,7 +81,6 @@ SurfaceTexture::SurfaceTexture(GLuint tex) :
    mDefaultWidth(1),
    mDefaultWidth(1),
    mDefaultHeight(1),
    mDefaultHeight(1),
    mPixelFormat(PIXEL_FORMAT_RGBA_8888),
    mPixelFormat(PIXEL_FORMAT_RGBA_8888),
    mUseDefaultSize(true),
    mBufferCount(MIN_BUFFER_SLOTS),
    mBufferCount(MIN_BUFFER_SLOTS),
    mCurrentTexture(INVALID_BUFFER_SLOT),
    mCurrentTexture(INVALID_BUFFER_SLOT),
    mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
    mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
@@ -133,8 +132,7 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
    return OK;
    return OK;
}
}


sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
    LOGV("SurfaceTexture::requestBuffer");
    LOGV("SurfaceTexture::requestBuffer");
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);
    if (buf < 0 || mBufferCount <= buf) {
    if (buf < 0 || mBufferCount <= buf) {
@@ -142,11 +140,34 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
                mBufferCount, buf);
                mBufferCount, buf);
        return 0;
        return 0;
    }
    }
    return mSlots[buf].mGraphicBuffer;
}

status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        uint32_t format, uint32_t usage) {
    LOGV("SurfaceTexture::dequeueBuffer");

    if ((w && !h) || (!w & h)) {
    if ((w && !h) || (!w & h)) {
        LOGE("requestBuffer: invalid size: w=%u, h=%u: %d", w, h, buf);
        LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
        return 0;
        return BAD_VALUE;
    }
    }


    Mutex::Autolock lock(mMutex);
    int found = INVALID_BUFFER_SLOT;
    for (int i = 0; i < mBufferCount; i++) {
        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
            mSlots[i].mOwnedByClient = true;
            found = i;
            break;
        }
    }
    if (found == INVALID_BUFFER_SLOT) {
        return -EBUSY;
    }

    const int buf = found;
    *outBuf = found;

    const bool useDefaultSize = !w && !h;
    const bool useDefaultSize = !w && !h;
    if (useDefaultSize) {
    if (useDefaultSize) {
        // use the default size
        // use the default size
@@ -160,13 +181,20 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
        format = mPixelFormat;
        format = mPixelFormat;
    }
    }


    const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
    if ((buffer == NULL) ||
        (uint32_t(buffer->width)  != w) ||
        (uint32_t(buffer->height) != h) ||
        (uint32_t(buffer->format) != format) ||
        ((uint32_t(buffer->usage) & usage) != usage))
    {
        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
        sp<GraphicBuffer> graphicBuffer(
        sp<GraphicBuffer> graphicBuffer(
                mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
                mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
        if (graphicBuffer == 0) {
        if (graphicBuffer == 0) {
        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
            LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
    } else {
            return NO_MEMORY;
        mUseDefaultSize = useDefaultSize;
        }
        if (updateFormat) {
        if (updateFormat) {
            mPixelFormat = format;
            mPixelFormat = format;
        }
        }
@@ -176,35 +204,6 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
        }
        }
    }
    return graphicBuffer;
}

status_t SurfaceTexture::dequeueBuffer(int *buf) {
    LOGV("SurfaceTexture::dequeueBuffer");
    Mutex::Autolock lock(mMutex);
    int found = INVALID_BUFFER_SLOT;
    for (int i = 0; i < mBufferCount; i++) {
        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
            mSlots[i].mOwnedByClient = true;
            found = i;
            break;
        }
    }
    if (found == INVALID_BUFFER_SLOT) {
        return -EBUSY;
    }

    *buf = found;

    const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
    if (buffer == NULL) {
        return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
    }

    if ((mUseDefaultSize) &&
        ((uint32_t(buffer->width) != mDefaultWidth) ||
         (uint32_t(buffer->height) != mDefaultHeight))) {
        return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
        return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
    }
    }
    return OK;
    return OK;
+6 −10
Original line number Original line Diff line number Diff line
@@ -97,20 +97,16 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
    LOGV("SurfaceTextureClient::dequeueBuffer");
    LOGV("SurfaceTextureClient::dequeueBuffer");
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);
    int buf = -1;
    int buf = -1;
    status_t err = mSurfaceTexture->dequeueBuffer(&buf);
    status_t err = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,
            mReqFormat, mReqUsage);
    if (err < 0) {
    if (err < 0) {
        LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
        LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
             "failed: %d", err, mReqWidth, mReqHeight, mReqFormat, mReqUsage);
        return err;
        return err;
    }
    }
    sp<GraphicBuffer>& gbuf(mSlots[buf]);
    sp<GraphicBuffer>& gbuf(mSlots[buf]);
    if (err == ISurfaceTexture::BUFFER_NEEDS_REALLOCATION ||
    if (err == ISurfaceTexture::BUFFER_NEEDS_REALLOCATION || gbuf == 0) {
        gbuf == 0 ||
        gbuf = mSurfaceTexture->requestBuffer(buf);
        (mReqWidth && gbuf->getWidth() != mReqWidth) ||
        (mReqHeight && gbuf->getHeight() != mReqHeight) ||
        (mReqFormat && uint32_t(gbuf->getPixelFormat()) != mReqFormat) ||
        (gbuf->getUsage() & mReqUsage) != mReqUsage) {
        gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
                mReqFormat, mReqUsage);
        if (gbuf == 0) {
        if (gbuf == 0) {
            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
            return NO_MEMORY;
            return NO_MEMORY;