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

Commit c91077c9 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

surfaceflinger: remove support for context detaching

BufferLayerConsumer::detachFromContext and
BufferLayerConsumer::attachToContext are unused.

BufferLayerConsumer::bindTextureImageLocked used to support a
special case (see libgui_test's
SurfaceTextureMultiContextGLTest.AttachAfterDisplayTerminatedSucceeds)
because of context detaching, the support can be removed as well.

Test: builds
Change-Id: I169a57ebd1b99770ce5c1cc68aa5eb097c6f1b26
parent 005bf0ae
Loading
Loading
Loading
Loading
+12 −167
Original line number Diff line number Diff line
@@ -124,35 +124,7 @@ BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, u
        mTexTarget(texTarget),
        mEglDisplay(EGL_NO_DISPLAY),
        mEglContext(EGL_NO_CONTEXT),
        mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
        mAttached(true) {
    BLC_LOGV("BufferLayerConsumer");

    memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));

    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
}

BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
                                         bool useFenceSync, bool isControlledByApp)
      : ConsumerBase(bq, isControlledByApp),
        mCurrentCrop(Rect::EMPTY_RECT),
        mCurrentTransform(0),
        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
        mCurrentFence(Fence::NO_FENCE),
        mCurrentTimestamp(0),
        mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
        mCurrentFrameNumber(0),
        mDefaultWidth(1),
        mDefaultHeight(1),
        mFilteringEnabled(true),
        mTexName(0),
        mUseFenceSync(useFenceSync),
        mTexTarget(texTarget),
        mEglDisplay(EGL_NO_DISPLAY),
        mEglContext(EGL_NO_CONTEXT),
        mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
        mAttached(false) {
        mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
    BLC_LOGV("BufferLayerConsumer");

    memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
@@ -252,13 +224,6 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,

    int slot = item.mSlot;

    if (!mAttached) {
        BLC_LOGE("updateAndRelease: BufferLayerConsumer is not attached to an OpenGL "
                 "ES context");
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
        return INVALID_OPERATION;
    }

    // Confirm state.
    err = checkAndUpdateEglStateLocked();
    if (err != NO_ERROR) {
@@ -364,34 +329,14 @@ status_t BufferLayerConsumer::bindTextureImageLocked() {
    }
    mCurrentTextureImage->bindToTextureTarget(mTexTarget);

    // In the rare case that the display is terminated and then initialized
    // again, we can't detect that the display changed (it didn't), but the
    // image is invalid. In this case, repeat the exact same steps while
    // forcing the creation of a new image.
    if ((error = glGetError()) != GL_NO_ERROR) {
        glBindTexture(mTexTarget, mTexName);
        status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, mCurrentCrop, true);
        if (result != NO_ERROR) {
            BLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
                     mCurrentTexture);
            return UNKNOWN_ERROR;
        }
        mCurrentTextureImage->bindToTextureTarget(mTexTarget);
        if ((error = glGetError()) != GL_NO_ERROR) {
            BLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
            return UNKNOWN_ERROR;
        }
    }

    // Wait for the new buffer to be ready.
    return doGLFenceWaitLocked();
}

status_t BufferLayerConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
status_t BufferLayerConsumer::checkAndUpdateEglStateLocked() {
    EGLDisplay dpy = eglGetCurrentDisplay();
    EGLContext ctx = eglGetCurrentContext();

    if (!contextCheck) {
    // if this is the first time we're called, mEglDisplay/mEglContext have
    // never been set, so don't error out (below).
    if (mEglDisplay == EGL_NO_DISPLAY) {
@@ -400,7 +345,6 @@ status_t BufferLayerConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
    if (mEglContext == EGL_NO_CONTEXT) {
        mEglContext = ctx;
    }
    }

    if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
        BLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
@@ -412,8 +356,6 @@ status_t BufferLayerConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
        return INVALID_OPERATION;
    }

    mEglDisplay = dpy;
    mEglContext = ctx;
    return NO_ERROR;
}

@@ -427,103 +369,6 @@ void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
    }
}

status_t BufferLayerConsumer::detachFromContext() {
    ATRACE_CALL();
    BLC_LOGV("detachFromContext");
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        BLC_LOGE("detachFromContext: abandoned BufferLayerConsumer");
        return NO_INIT;
    }

    if (!mAttached) {
        BLC_LOGE("detachFromContext: BufferLayerConsumer is not attached to a "
                 "context");
        return INVALID_OPERATION;
    }

    EGLDisplay dpy = eglGetCurrentDisplay();
    EGLContext ctx = eglGetCurrentContext();

    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
        BLC_LOGE("detachFromContext: invalid current EGLDisplay");
        return INVALID_OPERATION;
    }

    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
        BLC_LOGE("detachFromContext: invalid current EGLContext");
        return INVALID_OPERATION;
    }

    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
        status_t err = syncForReleaseLocked(dpy);
        if (err != OK) {
            return err;
        }

        glDeleteTextures(1, &mTexName);
    }

    mEglDisplay = EGL_NO_DISPLAY;
    mEglContext = EGL_NO_CONTEXT;
    mAttached = false;

    return OK;
}

status_t BufferLayerConsumer::attachToContext(uint32_t tex) {
    ATRACE_CALL();
    BLC_LOGV("attachToContext");
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        BLC_LOGE("attachToContext: abandoned BufferLayerConsumer");
        return NO_INIT;
    }

    if (mAttached) {
        BLC_LOGE("attachToContext: BufferLayerConsumer is already attached to a "
                 "context");
        return INVALID_OPERATION;
    }

    EGLDisplay dpy = eglGetCurrentDisplay();
    EGLContext ctx = eglGetCurrentContext();

    if (dpy == EGL_NO_DISPLAY) {
        BLC_LOGE("attachToContext: invalid current EGLDisplay");
        return INVALID_OPERATION;
    }

    if (ctx == EGL_NO_CONTEXT) {
        BLC_LOGE("attachToContext: invalid current EGLContext");
        return INVALID_OPERATION;
    }

    // We need to bind the texture regardless of whether there's a current
    // buffer.
    glBindTexture(mTexTarget, GLuint(tex));

    mEglDisplay = dpy;
    mEglContext = ctx;
    mTexName = tex;
    mAttached = true;

    if (mCurrentTextureImage != NULL) {
        // This may wait for a buffer a second time. This is likely required if
        // this is a different context, since otherwise the wait could be skipped
        // by bouncing through another context. For the same context the extra
        // wait is redundant.
        status_t err = bindTextureImageLocked();
        if (err != NO_ERROR) {
            return err;
        }
    }

    return OK;
}

status_t BufferLayerConsumer::syncForReleaseLocked(EGLDisplay dpy) {
    BLC_LOGV("syncForReleaseLocked");

@@ -894,13 +739,13 @@ BufferLayerConsumer::EglImage::~EglImage() {
    }
}

status_t BufferLayerConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, const Rect& cropRect,
                                                       bool forceCreation) {
status_t BufferLayerConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
                                                       const Rect& cropRect) {
    // If there's an image and it's no longer valid, destroy it.
    bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
    bool displayInvalid = mEglDisplay != eglDisplay;
    bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
    if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
    if (haveImage && (displayInvalid || cropInvalid)) {
        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
        }
+12 −72
Original line number Diff line number Diff line
@@ -44,9 +44,10 @@ class String8;
 * If a new frame is available, the texture will be updated.  If not,
 * the previous contents are retained.
 *
 * By default, the texture is attached to the GL_TEXTURE_EXTERNAL_OES
 * texture target, in the EGL context of the first thread that calls
 * updateTexImage().
 * The texture is attached to the GL_TEXTURE_EXTERNAL_OES texture target, in
 * the EGL context of the first thread that calls updateTexImage(). After that
 * point, all calls to updateTexImage must be made with the same OpenGL ES
 * context current.
 *
 * This class was previously called SurfaceTexture.
 */
@@ -55,38 +56,16 @@ public:
    enum { TEXTURE_EXTERNAL = 0x8D65 }; // GL_TEXTURE_EXTERNAL_OES
    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;

    // BufferLayerConsumer constructs a new BufferLayerConsumer object. If the constructor with
    // the tex parameter is used, tex indicates the name of the OpenGL ES
    // BufferLayerConsumer constructs a new BufferLayerConsumer object.
    // The tex parameter indicates the name of the OpenGL ES
    // texture to which images are to be streamed. texTarget specifies the
    // OpenGL ES texture target to which the texture will be bound in
    // updateTexImage. useFenceSync specifies whether fences should be used to
    // synchronize access to buffers if that behavior is enabled at
    // compile-time.
    //
    // A BufferLayerConsumer may be detached from one OpenGL ES context and then
    // attached to a different context using the detachFromContext and
    // attachToContext methods, respectively. The intention of these methods is
    // purely to allow a BufferLayerConsumer to be transferred from one consumer
    // context to another. If such a transfer is not needed there is no
    // requirement that either of these methods be called.
    //
    // If the constructor with the tex parameter is used, the BufferLayerConsumer is
    // created in a state where it is considered attached to an OpenGL ES
    // context for the purposes of the attachToContext and detachFromContext
    // methods. However, despite being considered "attached" to a context, the
    // specific OpenGL ES context doesn't get latched until the first call to
    // updateTexImage. After that point, all calls to updateTexImage must be
    // made with the same OpenGL ES context current.
    //
    // If the constructor without the tex parameter is used, the BufferLayerConsumer is
    // created in a detached state, and attachToContext must be called before
    // calls to updateTexImage.
    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t texureTarget,
                        bool useFenceSync, bool isControlledByApp);

    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texureTarget,
                        bool useFenceSync, bool isControlledByApp);

    // updateTexImage acquires the most recently queued buffer, and sets the
    // image contents of the target texture to it.
    //
@@ -195,33 +174,6 @@ public:
    // DEFAULT_USAGE_FLAGS to usage.
    status_t setConsumerUsageBits(uint64_t usage);

    // detachFromContext detaches the BufferLayerConsumer from the calling thread's
    // current OpenGL ES context.  This context must be the same as the context
    // that was current for previous calls to updateTexImage.
    //
    // Detaching a BufferLayerConsumer from an OpenGL ES context will result in the
    // deletion of the OpenGL ES texture object into which the images were being
    // streamed.  After a BufferLayerConsumer has been detached from the OpenGL ES
    // context calls to updateTexImage will fail returning INVALID_OPERATION
    // until the BufferLayerConsumer is attached to a new OpenGL ES context using the
    // attachToContext method.
    status_t detachFromContext();

    // attachToContext attaches a BufferLayerConsumer that is currently in the
    // 'detached' state to the current OpenGL ES context.  A BufferLayerConsumer is
    // in the 'detached' state iff detachFromContext has successfully been
    // called and no calls to attachToContext have succeeded since the last
    // detachFromContext call.  Calls to attachToContext made on a
    // BufferLayerConsumer that is not in the 'detached' state will result in an
    // INVALID_OPERATION error.
    //
    // The tex argument specifies the OpenGL ES texture object name in the
    // new context into which the image contents will be streamed.  A successful
    // call to attachToContext will result in this texture object being bound to
    // the texture target and populated with the image contents that were
    // current at the time of the last call to detachFromContext.
    status_t attachToContext(uint32_t tex);

protected:
    // abandonLocked overrides the ConsumerBase method to clear
    // mCurrentTextureImage in addition to the ConsumerBase behavior.
@@ -279,9 +231,7 @@ protected:
    // to mEglDisplay and mEglContext.  If the fields have been previously
    // set, the values must match; if not, the fields are set to the current
    // values.
    // The contextCheck argument is used to ensure that a GL context is
    // properly set; when set to false, the check is not performed.
    status_t checkAndUpdateEglStateLocked(bool contextCheck = false);
    status_t checkAndUpdateEglStateLocked();

private:
    // EglImage is a utility class for tracking and creating EGLImageKHRs. There
@@ -295,7 +245,7 @@ private:

        // createIfNeeded creates an EGLImage if required (we haven't created
        // one yet, or the EGLDisplay or crop-rect has changed).
        status_t createIfNeeded(EGLDisplay display, const Rect& cropRect, bool forceCreate = false);
        status_t createIfNeeded(EGLDisplay display, const Rect& cropRect);

        // This calls glEGLImageTargetTexture2DOES to bind the image to the
        // texture in the specified texture target.
@@ -411,9 +361,8 @@ private:
    bool mFilteringEnabled;

    // mTexName is the name of the OpenGL texture to which streamed images will
    // be bound when updateTexImage is called. It is set at construction time
    // and can be changed with a call to attachToContext.
    uint32_t mTexName;
    // be bound when updateTexImage is called. It is set at construction time.
    const uint32_t mTexName;

    // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
    // extension should be used to prevent buffers from being dequeued before
@@ -447,14 +396,13 @@ private:

    // mEglDisplay is the EGLDisplay with which this BufferLayerConsumer is currently
    // associated.  It is intialized to EGL_NO_DISPLAY and gets set to the
    // current display when updateTexImage is called for the first time and when
    // attachToContext is called.
    // current display when updateTexImage is called for the first time.
    EGLDisplay mEglDisplay;

    // mEglContext is the OpenGL ES context with which this BufferLayerConsumer is
    // currently associated.  It is initialized to EGL_NO_CONTEXT and gets set
    // to the current GL context when updateTexImage is called for the first
    // time and when attachToContext is called.
    // time.
    EGLContext mEglContext;

    // mEGLSlots stores the buffers that have been allocated by the BufferQueue
@@ -473,14 +421,6 @@ private:
    // that no buffer is bound to the texture. A call to setBufferCount will
    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
    int mCurrentTexture;

    // mAttached indicates whether the ConsumerBase is currently attached to
    // an OpenGL ES context.  For legacy reasons, this is initialized to true,
    // indicating that the ConsumerBase is considered to be attached to
    // whatever context is current at the time of the first updateTexImage call.
    // It is set to false by detachFromContext, and then set to true again by
    // attachToContext.
    bool mAttached;
};

// ----------------------------------------------------------------------------