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 Original line Diff line number Diff line
@@ -243,13 +243,9 @@ protected:
    status_t releaseAndUpdateLocked(const BufferQueue::BufferItem& item);
    status_t releaseAndUpdateLocked(const BufferQueue::BufferItem& item);


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

    status_t bindTextureImageLocked();
    // 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;


    // Gets the current EGLDisplay and EGLContext values, and compares them
    // Gets the current EGLDisplay and EGLContext values, and compares them
    // to mEglDisplay and mEglContext.  If the fields have been previously
    // to mEglDisplay and mEglContext.  If the fields have been previously
@@ -257,6 +253,10 @@ protected:
    // values.
    // values.
    status_t checkAndUpdateEglStateLocked();
    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:
private:
    // createImage creates a new EGLImage from a GraphicBuffer.
    // createImage creates a new EGLImage from a GraphicBuffer.
    EGLImageKHR createImage(EGLDisplay dpy,
    EGLImageKHR createImage(EGLDisplay dpy,
@@ -275,6 +275,11 @@ private:
    // mCurrentTextureBuf must not be NULL.
    // mCurrentTextureBuf must not be NULL.
    void computeCurrentTransformMatrixLocked();
    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
    // syncForReleaseLocked performs the synchronization needed to release the
    // current slot from an OpenGL ES context.  If needed it will set 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
    // current slot's fence to guard against a producer accessing the buffer
+16 −16
Original line number Original line Diff line number Diff line
@@ -39,6 +39,8 @@
#include <utils/String8.h>
#include <utils/String8.h>
#include <utils/Trace.h>
#include <utils/Trace.h>


namespace android {

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


// This compile option makes SurfaceTexture use the EGL_ANDROID_sync_wait
// 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_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)


namespace android {

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


    // Bind the new buffer to the GL texture.
    // Bind the new buffer to the GL texture, and wait until it's ready.
    err = bindTextureImage();
    return bindTextureImageLocked();
    if (err != NO_ERROR) {
        return err;
    }

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


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


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


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

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

}
}


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


    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (useNativeFenceSync) {
        if (sUseNativeFenceSync) {
            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
            if (sync == EGL_NO_SYNC_KHR) {
            if (sync == EGL_NO_SYNC_KHR) {
+3 −9
Original line number Original line Diff line number Diff line
@@ -327,17 +327,11 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
        return;
        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();
    status_t err = mSurfaceFlingerConsumer->bindTextureImage();
    if (err != NO_ERROR) {
    if (err != NO_ERROR) {
        ALOGW("Layer::onDraw: bindTextureImage failed");
        ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
        // 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);
        // Go ahead and draw the buffer anyway; no matter what we do the screen
        // Go ahead and draw the buffer anyway; no matter what we do the screen
        // is probably going to have something visibly wrong.
        // is probably going to have something visibly wrong.
    }
    }
+18 −6
Original line number Original line Diff line number Diff line
@@ -77,12 +77,24 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter)
        return err;
        return err;
    }
    }


    if (!sUseNativeFenceSync) {
        // Bind the new buffer to the GL texture.
        // Bind the new buffer to the GL texture.
    // TODO: skip this on devices that support explicit sync
        //
    // (glEGLImageTargetTexture2DOES provides required implicit sync;
        // Older devices require the "implicit" synchronization provided
    // without this we get wedged on older devices, but newer devices
        // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
    // don't need it.)
        // devices will either call this in Layer::onDraw, or (if it's not
    return bindTextureImage();
        // 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 Original line Diff line number Diff line
@@ -49,8 +49,8 @@ public:
    // texture.
    // texture.
    status_t updateTexImage(BufferRejecter* rejecter);
    status_t updateTexImage(BufferRejecter* rejecter);


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


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