10469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy/*
20469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Copyright 2011, The Android Open Source Project
30469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
40469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Licensed under the Apache License, Version 2.0 (the "License");
50469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * you may not use this file except in compliance with the License.
60469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * You may obtain a copy of the License at
70469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
80469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *     http://www.apache.org/licenses/LICENSE-2.0
90469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *
100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * Unless required by applicable law or agreed to in writing, software
110469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * distributed under the License is distributed on an "AS IS" BASIS,
120469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * See the License for the specific language governing permissions and
140469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy * limitations under the License.
150469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy */
160469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
173f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy#include <arpa/inet.h>
180469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <stdlib.h>
190469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <cutils/log.h>
200469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include <cutils/properties.h>
210469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
220469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "hooks.h"
230469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "glestrace.h"
240469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_context.h"
260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_egl.h"
270469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_hooks.h"
280469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy#include "gltrace_transport.h"
290469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
300469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamynamespace android {
310469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3293a826f78f6313db791e6fc880439189897651b3Siva Velusamyusing gltrace::GLTraceState;
3393a826f78f6313db791e6fc880439189897651b3Siva Velusamyusing gltrace::GLTraceContext;
3493a826f78f6313db791e6fc880439189897651b3Siva Velusamyusing gltrace::TCPStream;
350469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
3693a826f78f6313db791e6fc880439189897651b3Siva Velusamystatic GLTraceState *sGLTraceState;
373f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamystatic pthread_t sReceiveThreadId;
383f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
393f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy/**
403f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy * Task that monitors the control stream from the host and updates
413f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy * the trace status according to commands received from the host.
423f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy */
433f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamystatic void *commandReceiveTask(void *arg) {
443f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    GLTraceState *state = (GLTraceState *)arg;
453f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    TCPStream *stream = state->getStream();
463f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
472fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    // The control stream always receives an integer size of the
482fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    // command buffer, followed by the actual command buffer.
492fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    uint32_t cmdSize;
502fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
512fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    // Command Buffer
522fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    void *cmdBuf = NULL;
532fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    uint32_t cmdBufSize = 0;
542fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
553f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    enum TraceSettingsMasks {
563f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        READ_FB_ON_EGLSWAP_MASK = 1 << 0,
573f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        READ_FB_ON_GLDRAW_MASK = 1 << 1,
583f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK = 1 << 2,
593f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    };
603f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
613f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    while (true) {
622fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        // read command size
632fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (stream->receive(&cmdSize, sizeof(uint32_t)) < 0) {
643f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy            break;
653f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        }
662fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        cmdSize = ntohl(cmdSize);
672fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
682fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        // ensure command buffer is of required size
692fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (cmdBufSize < cmdSize) {
702fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            free(cmdBuf);
712fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            cmdBufSize = cmdSize;
722fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            cmdBuf = malloc(cmdSize);
732fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            if (cmdBuf == NULL)
742fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy                break;
752fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        }
763f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
772fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        // receive the command
782fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (stream->receive(cmdBuf, cmdSize) < 0) {
792fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            break;
802fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        }
812fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
822fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (cmdSize != sizeof(uint32_t)) {
832fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            // Currently, we only support commands that are a single integer,
842fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            // so we skip all other commands
852fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            continue;
862fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        }
872fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
882fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        uint32_t cmd = ntohl(*(uint32_t*)cmdBuf);
893f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
903f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        bool collectFbOnEglSwap = (cmd & READ_FB_ON_EGLSWAP_MASK) != 0;
913f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        bool collectFbOnGlDraw = (cmd & READ_FB_ON_GLDRAW_MASK) != 0;
923f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        bool collectTextureData = (cmd & READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK) != 0;
933f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
943f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        state->setCollectFbOnEglSwap(collectFbOnEglSwap);
953f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        state->setCollectFbOnGlDraw(collectFbOnGlDraw);
963f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        state->setCollectTextureDataOnGlTexImage(collectTextureData);
973f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
983f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        ALOGD("trace options: eglswap: %d, gldraw: %d, texImage: %d",
993f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy            collectFbOnEglSwap, collectFbOnGlDraw, collectTextureData);
1003f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    }
1013f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
1022fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    ALOGE("Stopping OpenGL Trace Command Receiver\n");
1032fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
1042fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    free(cmdBuf);
1053f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    return NULL;
1063f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy}
1070469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1080469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyvoid GLTrace_start() {
1090832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    char udsName[PROPERTY_VALUE_MAX];
1100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1110832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    property_get("debug.egl.debug_portname", udsName, "gltrace");
1120832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    int clientSocket = gltrace::acceptClientConnection(udsName);
11393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (clientSocket < 0) {
114e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block        ALOGE("Error creating GLTrace server socket. Quitting application.");
11593a826f78f6313db791e6fc880439189897651b3Siva Velusamy        exit(-1);
11693a826f78f6313db791e6fc880439189897651b3Siva Velusamy    }
11793a826f78f6313db791e6fc880439189897651b3Siva Velusamy
11893a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // create communication channel to the host
11993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    TCPStream *stream = new TCPStream(clientSocket);
12093a826f78f6313db791e6fc880439189897651b3Siva Velusamy
12193a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // initialize tracing state
12293a826f78f6313db791e6fc880439189897651b3Siva Velusamy    sGLTraceState = new GLTraceState(stream);
1233f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
1243f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    pthread_create(&sReceiveThreadId, NULL, commandReceiveTask, sGLTraceState);
1250469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1260469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1270469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyvoid GLTrace_stop() {
12893a826f78f6313db791e6fc880439189897651b3Siva Velusamy    delete sGLTraceState;
12993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    sGLTraceState = NULL;
1300469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1310469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
13293a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid GLTrace_eglCreateContext(int version, EGLContext c) {
13393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // update trace state for new EGL context
13493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    GLTraceContext *traceContext = sGLTraceState->createTraceContext(version, c);
13593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::setupTraceContextThreadSpecific(traceContext);
13693a826f78f6313db791e6fc880439189897651b3Siva Velusamy
13793a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // trace command through to the host
13893a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::GLTrace_eglCreateContext(version, traceContext->getId());
13993a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
14093a826f78f6313db791e6fc880439189897651b3Siva Velusamy
14193a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks, EGLContext c) {
14293a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // setup per context state
14393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    GLTraceContext *traceContext = sGLTraceState->getTraceContext(c);
14493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    traceContext->hooks = hooks;
14593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::setupTraceContextThreadSpecific(traceContext);
14693a826f78f6313db791e6fc880439189897651b3Siva Velusamy
14793a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // trace command through to the host
14893a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::GLTrace_eglMakeCurrent(traceContext->getId());
14993a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
15093a826f78f6313db791e6fc880439189897651b3Siva Velusamy
15193a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid GLTrace_eglReleaseThread() {
15293a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::releaseContext();
1530469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1540469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1550469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyvoid GLTrace_eglSwapBuffers(void *dpy, void *draw) {
1560469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    gltrace::GLTrace_eglSwapBuffers(dpy, draw);
1570469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1580469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
15993a826f78f6313db791e6fc880439189897651b3Siva Velusamygl_hooks_t *GLTrace_getGLHooks() {
16093a826f78f6313db791e6fc880439189897651b3Siva Velusamy    return gltrace::getGLHooks();
16193a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
16293a826f78f6313db791e6fc880439189897651b3Siva Velusamy
1630469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
164