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

Commit 3f194e6e authored by Siva Velusamy's avatar Siva Velusamy
Browse files

gltrace: add user settings to control data captured.

Currently users do not have control over the amount of data
captured during tracing. This patch adds 3 settings that users
can enable/disable at runtime:
  - capture framebuffer on eglSwap() calls
  - capture framebuffer on glDraw*() calls
  - capture texture data passed to glTexImage*() calls
Disabling these options when not needed signficantly decreases
the size of the trace file, and reduces performance overhead for
the running application.

These settings are stored in the per process GLTraceState.
A separate thread listens for commands from the host, and updates
the state based on the user commands.

Change-Id: Ic4518b94e8bcbc5330ac7138153721caa98b365d
parent 875bdea8
Loading
Loading
Loading
Loading
+49 −2
Original line number Diff line number Diff line
@@ -59,6 +59,11 @@ void releaseContext() {
GLTraceState::GLTraceState(TCPStream *stream) {
    mTraceContextIds = 0;
    mStream = stream;

    mCollectFbOnEglSwap = false;
    mCollectFbOnGlDraw = false;
    mCollectTextureDataOnGlTexImage = false;
    pthread_rwlock_init(&mTraceOptionsRwLock, NULL);
}

GLTraceState::~GLTraceState() {
@@ -72,12 +77,49 @@ TCPStream *GLTraceState::getStream() {
    return mStream;
}

void GLTraceState::safeSetValue(bool *ptr, bool value, pthread_rwlock_t *lock) {
    pthread_rwlock_wrlock(lock);
    *ptr = value;
    pthread_rwlock_unlock(lock);
}

bool GLTraceState::safeGetValue(bool *ptr, pthread_rwlock_t *lock) {
    pthread_rwlock_rdlock(lock);
    bool value = *ptr;
    pthread_rwlock_unlock(lock);
    return value;
}

void GLTraceState::setCollectFbOnEglSwap(bool en) {
    safeSetValue(&mCollectFbOnEglSwap, en, &mTraceOptionsRwLock);
}

void GLTraceState::setCollectFbOnGlDraw(bool en) {
    safeSetValue(&mCollectFbOnGlDraw, en, &mTraceOptionsRwLock);
}

void GLTraceState::setCollectTextureDataOnGlTexImage(bool en) {
    safeSetValue(&mCollectTextureDataOnGlTexImage, en, &mTraceOptionsRwLock);
}

bool GLTraceState::shouldCollectFbOnEglSwap() {
    return safeGetValue(&mCollectFbOnEglSwap, &mTraceOptionsRwLock);
}

bool GLTraceState::shouldCollectFbOnGlDraw() {
    return safeGetValue(&mCollectFbOnGlDraw, &mTraceOptionsRwLock);
}

bool GLTraceState::shouldCollectTextureDataOnGlTexImage() {
    return safeGetValue(&mCollectTextureDataOnGlTexImage, &mTraceOptionsRwLock);
}

GLTraceContext *GLTraceState::createTraceContext(int version, EGLContext eglContext) {
    int id = __sync_fetch_and_add(&mTraceContextIds, 1);

    const size_t DEFAULT_BUFFER_SIZE = 8192;
    BufferedOutputStream *stream = new BufferedOutputStream(mStream, DEFAULT_BUFFER_SIZE);
    GLTraceContext *traceContext = new GLTraceContext(id, stream);
    GLTraceContext *traceContext = new GLTraceContext(id, this, stream);
    mPerContextState[eglContext] = traceContext;

    return traceContext;
@@ -87,8 +129,9 @@ GLTraceContext *GLTraceState::getTraceContext(EGLContext c) {
    return mPerContextState[c];
}

GLTraceContext::GLTraceContext(int id, BufferedOutputStream *stream) {
GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) {
    mId = id;
    mState = state;

    fbcontents = fbcompressed = NULL;
    fbcontentsSize = 0;
@@ -99,6 +142,10 @@ int GLTraceContext::getId() {
    return mId;
}

GLTraceState *GLTraceContext::getGlobalTraceState() {
    return mState;
}

void GLTraceContext::resizeFBMemory(unsigned minSize) {
    if (fbcontentsSize >= minSize) {
        return;
+27 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define __GLTRACE_CONTEXT_H_

#include <map>
#include <pthread.h>

#include "hooks.h"
#include "gltrace_transport.h"
@@ -29,9 +30,12 @@ using ::android::gl_hooks_t;

enum FBBinding {CURRENTLY_BOUND_FB, FB0};

class GLTraceState;

/** GL Trace Context info associated with each EGLContext */
class GLTraceContext {
    int mId;                    /* unique context id */
    GLTraceState *mState;       /* parent GL Trace state (for per process GL Trace State Info) */

    void *fbcontents;           /* memory area to read framebuffer contents */
    void *fbcompressed;         /* destination for lzf compressed framebuffer */
@@ -43,8 +47,9 @@ class GLTraceContext {
public:
    gl_hooks_t *hooks;

    GLTraceContext(int id, BufferedOutputStream *stream);
    GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream);
    int getId();
    GLTraceState *getGlobalTraceState();
    void getCompressedFB(void **fb, unsigned *fbsize,
                            unsigned *fbwidth, unsigned *fbheight,
                            FBBinding fbToRead);
@@ -56,6 +61,17 @@ class GLTraceState {
    int mTraceContextIds;
    TCPStream *mStream;
    std::map<EGLContext, GLTraceContext*> mPerContextState;

    /* Options controlling additional data to be collected on
       certain trace calls. */
    bool mCollectFbOnEglSwap;
    bool mCollectFbOnGlDraw;
    bool mCollectTextureDataOnGlTexImage;
    pthread_rwlock_t mTraceOptionsRwLock;

    /* helper methods to get/set values using provided lock for mutual exclusion. */
    void safeSetValue(bool *ptr, bool value, pthread_rwlock_t *lock);
    bool safeGetValue(bool *ptr, pthread_rwlock_t *lock);
public:
    GLTraceState(TCPStream *stream);
    ~GLTraceState();
@@ -64,6 +80,16 @@ public:
    GLTraceContext *getTraceContext(EGLContext c);

    TCPStream *getStream();

    /* Methods to set trace options. */
    void setCollectFbOnEglSwap(bool en);
    void setCollectFbOnGlDraw(bool en);
    void setCollectTextureDataOnGlTexImage(bool en);

    /* Methods to retrieve trace options. */
    bool shouldCollectFbOnEglSwap();
    bool shouldCollectFbOnGlDraw();
    bool shouldCollectTextureDataOnGlTexImage();
};

void setupTraceContextThreadSpecific(GLTraceContext *context);
+4 −2
Original line number Diff line number Diff line
@@ -78,8 +78,10 @@ void GLTrace_eglSwapBuffers(void *dpy, void *draw) {
    glmessage.set_context_id(glContext->getId());
    glmessage.set_function(GLMessage::eglSwapBuffers);

    if (glContext->getGlobalTraceState()->shouldCollectFbOnEglSwap()) {
        // read FB0 since that is what is displayed on the screen
        fixup_addFBContents(glContext, &glmessage, FB0);
    }

    // set start time and duration
    glmessage.set_start_time(systemTime());
+44 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 */

#include <arpa/inet.h>
#include <stdlib.h>
#include <cutils/log.h>
#include <cutils/properties.h>
@@ -33,6 +34,47 @@ using gltrace::GLTraceContext;
using gltrace::TCPStream;

static GLTraceState *sGLTraceState;
static pthread_t sReceiveThreadId;

/**
 * Task that monitors the control stream from the host and updates
 * the trace status according to commands received from the host.
 */
static void *commandReceiveTask(void *arg) {
    GLTraceState *state = (GLTraceState *)arg;
    TCPStream *stream = state->getStream();

    // Currently, there are very few user configurable settings.
    // As a result, they can be encoded in a single integer.
    int cmd;
    enum TraceSettingsMasks {
        READ_FB_ON_EGLSWAP_MASK = 1 << 0,
        READ_FB_ON_GLDRAW_MASK = 1 << 1,
        READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK = 1 << 2,
    };

    while (true) {
        int n = stream->receive(&cmd, 4);
        if (n != 4) {
            break;
        }

        cmd = ntohl(cmd);

        bool collectFbOnEglSwap = (cmd & READ_FB_ON_EGLSWAP_MASK) != 0;
        bool collectFbOnGlDraw = (cmd & READ_FB_ON_GLDRAW_MASK) != 0;
        bool collectTextureData = (cmd & READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK) != 0;

        state->setCollectFbOnEglSwap(collectFbOnEglSwap);
        state->setCollectFbOnGlDraw(collectFbOnGlDraw);
        state->setCollectTextureDataOnGlTexImage(collectTextureData);

        ALOGD("trace options: eglswap: %d, gldraw: %d, texImage: %d",
            collectFbOnEglSwap, collectFbOnGlDraw, collectTextureData);
    }

    return NULL;
}

void GLTrace_start() {
    char value[PROPERTY_VALUE_MAX];
@@ -51,6 +93,8 @@ void GLTrace_start() {

    // initialize tracing state
    sGLTraceState = new GLTraceState(stream);

    pthread_create(&sReceiveThreadId, NULL, commandReceiveTask, sGLTraceState);
}

void GLTrace_stop() {
+11 −3
Original line number Diff line number Diff line
@@ -283,7 +283,9 @@ void fixupGLMessage(GLTraceContext *context, nsecs_t start, nsecs_t end, GLMessa
        fixup_glGetString(glmsg);
        break;
    case GLMessage::glTexImage2D:
        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
            fixup_glTexImage2D(glmsg);
        }
        break;
    case GLMessage::glShaderSource:
        fixup_glShaderSource(glmsg);
@@ -304,10 +306,16 @@ void fixupGLMessage(GLTraceContext *context, nsecs_t start, nsecs_t end, GLMessa
        fixup_glUniformMatrixGeneric(4, glmsg);
        break;
    case GLMessage::glDrawArrays:
    case GLMessage::glDrawElements:
        /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
        }
        break;
    case GLMessage::glDrawElements:
        /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
        }
        break;
    default:
        break;