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

Commit 97eba890 authored by Andy McFadden's avatar Andy McFadden
Browse files

Avoid unnecessary texture bind

In SurfaceFlingerConsumer, check to see if native fence sync is
enabled.  If so, defer the texture binding step to Layer::onDraw.

Change-Id: I7d4034a31c0143207eea2509dfa13ef3820f9b8c
parent 3325fe16
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -243,13 +243,9 @@ protected:
    status_t releaseAndUpdateLocked(const BufferQueue::BufferItem& item);

    // Binds mTexName and the current buffer to mTexTarget.  Uses
    // mCurrentTexture if it's set, mCurrentTextureBuf if not.
    status_t bindTextureImage();

    // doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
    // stream to ensure that it is safe for future OpenGL ES commands to
    // access the current texture buffer.
    status_t doGLFenceWaitLocked() const;
    // mCurrentTexture if it's set, mCurrentTextureBuf if not.  If the
    // bind succeeds, this calls doGLFenceWait.
    status_t bindTextureImageLocked();

    // Gets the current EGLDisplay and EGLContext values, and compares them
    // to mEglDisplay and mEglContext.  If the fields have been previously
@@ -257,6 +253,10 @@ protected:
    // values.
    status_t checkAndUpdateEglStateLocked();

    // If set, SurfaceTexture will use the EGL_ANDROID_native_fence_sync
    // extension to create Android native fences for GLES activity.
    static const bool sUseNativeFenceSync;

private:
    // createImage creates a new EGLImage from a GraphicBuffer.
    EGLImageKHR createImage(EGLDisplay dpy,
@@ -275,6 +275,11 @@ private:
    // mCurrentTextureBuf must not be NULL.
    void computeCurrentTransformMatrixLocked();

    // doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
    // stream to ensure that it is safe for future OpenGL ES commands to
    // access the current texture buffer.
    status_t doGLFenceWaitLocked() const;

    // syncForReleaseLocked performs the synchronization needed to release the
    // current slot from an OpenGL ES context.  If needed it will set the
    // current slot's fence to guard against a producer accessing the buffer
+16 −16
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@
#include <utils/String8.h>
#include <utils/Trace.h>

namespace android {

// This compile option makes SurfaceTexture use the
// EGL_ANDROID_native_fence_sync extension to create Android native fences to
// signal when all GLES reads for a given buffer have completed.  It is not
@@ -48,9 +50,9 @@
#ifdef USE_FENCE_SYNC
#error "USE_NATIVE_FENCE_SYNC and USE_FENCE_SYNC are incompatible"
#endif
static const bool useNativeFenceSync = true;
const bool SurfaceTexture::sUseNativeFenceSync = true;
#else
static const bool useNativeFenceSync = false;
const bool SurfaceTexture::sUseNativeFenceSync = false;
#endif

// This compile option makes SurfaceTexture use the EGL_ANDROID_sync_wait
@@ -70,8 +72,6 @@ static const bool useWaitSync = false;
#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)

namespace android {

// Transform matrices
static float mtxIdentity[16] = {
    1, 0, 0, 0,
@@ -196,14 +196,8 @@ status_t SurfaceTexture::updateTexImage() {
        return err;
    }

    // Bind the new buffer to the GL texture.
    err = bindTextureImage();
    if (err != NO_ERROR) {
        return err;
    }

    // Wait for the new buffer to be ready.
    return doGLFenceWaitLocked();
    // Bind the new buffer to the GL texture, and wait until it's ready.
    return bindTextureImageLocked();
}

status_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) {
@@ -313,7 +307,7 @@ status_t SurfaceTexture::releaseAndUpdateLocked(const BufferQueue::BufferItem& i
    return err;
}

status_t SurfaceTexture::bindTextureImage() {
status_t SurfaceTexture::bindTextureImageLocked() {
    if (mEglDisplay == EGL_NO_DISPLAY) {
        ALOGE("bindTextureImage: invalid display");
        return INVALID_OPERATION;
@@ -330,7 +324,10 @@ status_t SurfaceTexture::bindTextureImage() {
            ST_LOGE("bindTextureImage: no currently-bound texture");
            return NO_INIT;
        }
        return bindUnslottedBufferLocked(mEglDisplay);
        status_t err = bindUnslottedBufferLocked(mEglDisplay);
        if (err != NO_ERROR) {
            return err;
        }
    } else {
        EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;

@@ -341,8 +338,11 @@ status_t SurfaceTexture::bindTextureImage() {
                    ": %#04x", image, error);
            return UNKNOWN_ERROR;
        }
        return NO_ERROR;
    }

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

}

status_t SurfaceTexture::checkAndUpdateEglStateLocked() {
@@ -521,7 +521,7 @@ status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {
    ST_LOGV("syncForReleaseLocked");

    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (useNativeFenceSync) {
        if (sUseNativeFenceSync) {
            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
            if (sync == EGL_NO_SYNC_KHR) {
+3 −9
Original line number Diff line number Diff line
@@ -327,17 +327,11 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
        return;
    }

    // Bind the current buffer to the GL texture.
    // Bind the current buffer to the GL texture, and wait for it to be
    // ready for us to draw into.
    status_t err = mSurfaceFlingerConsumer->bindTextureImage();
    if (err != NO_ERROR) {
        ALOGW("Layer::onDraw: bindTextureImage failed");
        // keep going
    }

    // Wait for the buffer to be ready for us to draw into.
    err = mSurfaceFlingerConsumer->doGLFenceWait();
    if (err != OK) {
        ALOGE("onDraw: failed waiting for fence: %d", err);
        ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
        // Go ahead and draw the buffer anyway; no matter what we do the screen
        // is probably going to have something visibly wrong.
    }
+18 −6
Original line number Diff line number Diff line
@@ -77,12 +77,24 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter)
        return err;
    }

    if (!sUseNativeFenceSync) {
        // Bind the new buffer to the GL texture.
    // TODO: skip this on devices that support explicit sync
    // (glEGLImageTargetTexture2DOES provides required implicit sync;
    // without this we get wedged on older devices, but newer devices
    // don't need it.)
    return bindTextureImage();
        //
        // Older devices require the "implicit" synchronization provided
        // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
        // devices will either call this in Layer::onDraw, or (if it's not
        // a GL-composited layer) not at all.
        err = bindTextureImageLocked();
    }

    return err;
}

status_t SurfaceFlingerConsumer::bindTextureImage()
{
    Mutex::Autolock lock(mMutex);

    return bindTextureImageLocked();
}

// ---------------------------------------------------------------------------
+2 −2
Original line number Diff line number Diff line
@@ -49,8 +49,8 @@ public:
    // texture.
    status_t updateTexImage(BufferRejecter* rejecter);

    // Pass-through to SurfaceTexture implementation.
    status_t bindTextureImage() { return SurfaceTexture::bindTextureImage(); }
    // See SurfaceTexture::bindTextureImageLocked().
    status_t bindTextureImage();
};

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