/*
 * Copyright 2011, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <arpa/inet.h>
#include <stdlib.h>
#include <cutils/log.h>
#include <cutils/properties.h>

#include "hooks.h"
#include "glestrace.h"

#include "gltrace_context.h"
#include "gltrace_egl.h"
#include "gltrace_hooks.h"
#include "gltrace_transport.h"

namespace android {

using gltrace::GLTraceState;
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];

    property_get("debug.egl.debug_port", value, "5039");
    const unsigned short port = (unsigned short)atoi(value);

    int clientSocket = gltrace::acceptClientConnection(port);
    if (clientSocket < 0) {
        LOGE("Error creating GLTrace server socket. Quitting application.");
        exit(-1);
    }

    // create communication channel to the host
    TCPStream *stream = new TCPStream(clientSocket);

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

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

void GLTrace_stop() {
    delete sGLTraceState;
    sGLTraceState = NULL;
}

void GLTrace_eglCreateContext(int version, EGLContext c) {
    // update trace state for new EGL context
    GLTraceContext *traceContext = sGLTraceState->createTraceContext(version, c);
    gltrace::setupTraceContextThreadSpecific(traceContext);

    // trace command through to the host
    gltrace::GLTrace_eglCreateContext(version, traceContext->getId());
}

void GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks, EGLContext c) {
    // setup per context state
    GLTraceContext *traceContext = sGLTraceState->getTraceContext(c);
    traceContext->hooks = hooks;
    gltrace::setupTraceContextThreadSpecific(traceContext);

    // trace command through to the host
    gltrace::GLTrace_eglMakeCurrent(traceContext->getId());
}

void GLTrace_eglReleaseThread() {
    gltrace::releaseContext();
}

void GLTrace_eglSwapBuffers(void *dpy, void *draw) {
    gltrace::GLTrace_eglSwapBuffers(dpy, draw);
}

gl_hooks_t *GLTrace_getGLHooks() {
    return gltrace::getGLHooks();
}

}
