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
36a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamystatic pthread_mutex_t sGlTraceStateLock = PTHREAD_MUTEX_INITIALIZER;
37a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
38a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamystatic int sGlTraceInProgress;
3993a826f78f6313db791e6fc880439189897651b3Siva Velusamystatic GLTraceState *sGLTraceState;
403f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamystatic pthread_t sReceiveThreadId;
413f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
423f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy/**
433f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy * Task that monitors the control stream from the host and updates
443f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy * the trace status according to commands received from the host.
453f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy */
463f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamystatic void *commandReceiveTask(void *arg) {
473f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    GLTraceState *state = (GLTraceState *)arg;
483f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    TCPStream *stream = state->getStream();
493f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
502fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    // The control stream always receives an integer size of the
512fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    // command buffer, followed by the actual command buffer.
522fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    uint32_t cmdSize;
532fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
542fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    // Command Buffer
552fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    void *cmdBuf = NULL;
562fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    uint32_t cmdBufSize = 0;
572fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
583f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    enum TraceSettingsMasks {
593f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        READ_FB_ON_EGLSWAP_MASK = 1 << 0,
603f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        READ_FB_ON_GLDRAW_MASK = 1 << 1,
613f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK = 1 << 2,
623f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    };
633f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
643f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    while (true) {
652fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        // read command size
662fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (stream->receive(&cmdSize, sizeof(uint32_t)) < 0) {
673f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy            break;
683f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        }
692fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        cmdSize = ntohl(cmdSize);
702fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
712fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        // ensure command buffer is of required size
722fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (cmdBufSize < cmdSize) {
732fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            free(cmdBuf);
742fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            cmdBufSize = cmdSize;
752fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            cmdBuf = malloc(cmdSize);
762fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            if (cmdBuf == NULL)
772fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy                break;
782fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        }
793f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
802fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        // receive the command
812fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (stream->receive(cmdBuf, cmdSize) < 0) {
822fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            break;
832fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        }
842fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
852fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        if (cmdSize != sizeof(uint32_t)) {
862fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            // Currently, we only support commands that are a single integer,
872fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            // so we skip all other commands
882fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy            continue;
892fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        }
902fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
912fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy        uint32_t cmd = ntohl(*(uint32_t*)cmdBuf);
923f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
933f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        bool collectFbOnEglSwap = (cmd & READ_FB_ON_EGLSWAP_MASK) != 0;
943f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        bool collectFbOnGlDraw = (cmd & READ_FB_ON_GLDRAW_MASK) != 0;
953f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        bool collectTextureData = (cmd & READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK) != 0;
963f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
973f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        state->setCollectFbOnEglSwap(collectFbOnEglSwap);
983f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        state->setCollectFbOnGlDraw(collectFbOnGlDraw);
993f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        state->setCollectTextureDataOnGlTexImage(collectTextureData);
1003f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
1013f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy        ALOGD("trace options: eglswap: %d, gldraw: %d, texImage: %d",
1023f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy            collectFbOnEglSwap, collectFbOnGlDraw, collectTextureData);
1033f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    }
1043f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
1052fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    ALOGE("Stopping OpenGL Trace Command Receiver\n");
1062fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy
1072fdcc81ddfdbdfbbde63bd64e9ac9272b5417553Siva Velusamy    free(cmdBuf);
1083f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    return NULL;
1093f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy}
1100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
111a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy/**
112a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy * Starts Trace Server and waits for connection from the host.
113a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy * Returns -1 in case of connection error, 0 otherwise.
114a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy */
115a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamyint GLTrace_start() {
116a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    int status = 0;
117a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    int clientSocket = -1;
118a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    TCPStream *stream = NULL;
119a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
120a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_lock(&sGlTraceStateLock);
1210469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
122a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    if (sGlTraceInProgress) {
123a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        goto done;
124a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    }
125a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
126a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    char udsName[PROPERTY_VALUE_MAX];
1270832fb6407d1c85cba20a8cc0aff828db3c134deSiva Velusamy    property_get("debug.egl.debug_portname", udsName, "gltrace");
128a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    clientSocket = gltrace::acceptClientConnection(udsName);
12993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    if (clientSocket < 0) {
130a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        ALOGE("Error creating GLTrace server socket. Tracing disabled.");
131a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        status = -1;
132a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        goto done;
13393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    }
13493a826f78f6313db791e6fc880439189897651b3Siva Velusamy
135a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    sGlTraceInProgress = 1;
136a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
13793a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // create communication channel to the host
138a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    stream = new TCPStream(clientSocket);
13993a826f78f6313db791e6fc880439189897651b3Siva Velusamy
14093a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // initialize tracing state
14193a826f78f6313db791e6fc880439189897651b3Siva Velusamy    sGLTraceState = new GLTraceState(stream);
1423f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy
1433f194e6e3a62cbb846e8948eac8e4ce9aa7444a6Siva Velusamy    pthread_create(&sReceiveThreadId, NULL, commandReceiveTask, sGLTraceState);
144a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
145a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamydone:
146a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_unlock(&sGlTraceStateLock);
147a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    return status;
1480469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1490469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
1500469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyvoid GLTrace_stop() {
151a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_lock(&sGlTraceStateLock);
152a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
153a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    if (sGlTraceInProgress) {
154a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        sGlTraceInProgress = 0;
155a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        delete sGLTraceState;
156a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        sGLTraceState = NULL;
157a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    }
158a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
159a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_unlock(&sGlTraceStateLock);
1600469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
1610469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
16293a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid GLTrace_eglCreateContext(int version, EGLContext c) {
163a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_lock(&sGlTraceStateLock);
164a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    GLTraceState *state = sGLTraceState;
165a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_unlock(&sGlTraceStateLock);
166a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
167a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    if (state == NULL) return;
168a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
16993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // update trace state for new EGL context
170a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    GLTraceContext *traceContext = state->createTraceContext(version, c);
17193a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::setupTraceContextThreadSpecific(traceContext);
17293a826f78f6313db791e6fc880439189897651b3Siva Velusamy
17393a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // trace command through to the host
17493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::GLTrace_eglCreateContext(version, traceContext->getId());
17593a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
17693a826f78f6313db791e6fc880439189897651b3Siva Velusamy
17793a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks, EGLContext c) {
178a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_lock(&sGlTraceStateLock);
179a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    GLTraceState *state = sGLTraceState;
180a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    pthread_mutex_unlock(&sGlTraceStateLock);
181a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
182a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    if (state == NULL) return;
183a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
18493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // setup per context state
185a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    GLTraceContext *traceContext = state->getTraceContext(c);
186a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    if (traceContext == NULL) {
187a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        GLTrace_eglCreateContext(version, c);
188a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy        traceContext = state->getTraceContext(c);
189a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy    }
190a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy
19193a826f78f6313db791e6fc880439189897651b3Siva Velusamy    traceContext->hooks = hooks;
19293a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::setupTraceContextThreadSpecific(traceContext);
19393a826f78f6313db791e6fc880439189897651b3Siva Velusamy
19493a826f78f6313db791e6fc880439189897651b3Siva Velusamy    // trace command through to the host
19593a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::GLTrace_eglMakeCurrent(traceContext->getId());
19693a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
19793a826f78f6313db791e6fc880439189897651b3Siva Velusamy
19893a826f78f6313db791e6fc880439189897651b3Siva Velusamyvoid GLTrace_eglReleaseThread() {
19993a826f78f6313db791e6fc880439189897651b3Siva Velusamy    gltrace::releaseContext();
2000469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
2010469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
2020469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamyvoid GLTrace_eglSwapBuffers(void *dpy, void *draw) {
2030469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy    gltrace::GLTrace_eglSwapBuffers(dpy, draw);
2040469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
2050469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy
20693a826f78f6313db791e6fc880439189897651b3Siva Velusamygl_hooks_t *GLTrace_getGLHooks() {
20793a826f78f6313db791e6fc880439189897651b3Siva Velusamy    return gltrace::getGLHooks();
20893a826f78f6313db791e6fc880439189897651b3Siva Velusamy}
20993a826f78f6313db791e6fc880439189897651b3Siva Velusamy
2100469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy}
211