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

Commit c522a6a5 authored by Jamie Gennis's avatar Jamie Gennis Committed by Android (Google) Code Review
Browse files

Merge "EGL: add GPU frame completion tracing"

parents cb9be123 28ef8d79
Loading
Loading
Loading
Loading
+76 −1
Original line number Diff line number Diff line
@@ -715,6 +715,69 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
    return addr;
}

class FrameCompletionThread : public Thread {
public:

    static void queueSync(EGLSyncKHR sync) {
        static sp<FrameCompletionThread> thread(new FrameCompletionThread);
        static bool running = false;
        if (!running) {
            thread->run("GPUFrameCompletion");
            running = true;
        }
        {
            Mutex::Autolock lock(thread->mMutex);
            ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
                    thread->mFramesQueued).string());
            thread->mQueue.push_back(sync);
            thread->mCondition.signal();
            thread->mFramesQueued++;
            ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
        }
    }

private:
    FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}

    virtual bool threadLoop() {
        EGLSyncKHR sync;
        uint32_t frameNum;
        {
            Mutex::Autolock lock(mMutex);
            while (mQueue.isEmpty()) {
                mCondition.wait(mMutex);
            }
            sync = mQueue[0];
            frameNum = mFramesCompleted;
        }
        EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        {
            ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
                    frameNum).string());
            EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
            if (result == EGL_FALSE) {
                ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
            } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
                ALOGE("FrameCompletion: timeout waiting for fence");
            }
            eglDestroySyncKHR(dpy, sync);
        }
        {
            Mutex::Autolock lock(mMutex);
            mQueue.removeAt(0);
            mFramesCompleted++;
            ATRACE_INT("GPU Frames Outstanding", mQueue.size());
        }
        return true;
    }

    uint32_t mFramesQueued;
    uint32_t mFramesCompleted;
    Vector<EGLSyncKHR> mQueue;
    Condition mCondition;
    Mutex mMutex;
};

EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
    ATRACE_CALL();
@@ -744,7 +807,19 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
        }
    }

    return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
    EGLBoolean result = s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);

    if (CC_UNLIKELY(dp->traceGpuCompletion)) {
        EGLSyncKHR sync = EGL_NO_SYNC_KHR;
        {
            sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
        }
        if (sync != EGL_NO_SYNC_KHR) {
            FrameCompletionThread::queueSync(sync);
        }
    }

    return result;
}

EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
+6 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];

egl_display_t::egl_display_t() :
    magic('_dpy'), finishOnSwap(false), refs(0) {
    magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0) {
}

egl_display_t::~egl_display_t() {
@@ -239,6 +239,11 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
        finishOnSwap = true;
    }

    property_get("debug.egl.traceGpuCompletion", value, "0");
    if (atoi(value)) {
        traceGpuCompletion = true;
    }

    refs++;
    if (major != NULL)
        *major = VERSION_MAJOR;
+2 −1
Original line number Diff line number Diff line
@@ -107,7 +107,8 @@ private:

public:
    DisplayImpl     disp;
    bool    finishOnSwap;
    bool    finishOnSwap;       // property: debug.egl.finish
    bool    traceGpuCompletion; // property: debug.egl.traceGpuCompletion

private:
            uint32_t                    refs;