1/*
2* Copyright (C) 2011 The Android Open Source Project
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16#include "HostConnection.h"
17#include "TcpStream.h"
18#include "QemuPipeStream.h"
19#include "ThreadInfo.h"
20#include <cutils/log.h>
21#include "GLEncoder.h"
22#include "GL2Encoder.h"
23
24#define STREAM_BUFFER_SIZE  4*1024*1024
25#define STREAM_PORT_NUM     22468
26
27/* Set to 1 to use a QEMU pipe, or 0 for a TCP connection */
28#define  USE_QEMU_PIPE  1
29
30HostConnection::HostConnection() :
31    m_stream(NULL),
32    m_glEnc(NULL),
33    m_gl2Enc(NULL),
34    m_rcEnc(NULL)
35{
36}
37
38HostConnection::~HostConnection()
39{
40    delete m_stream;
41    delete m_glEnc;
42    delete m_gl2Enc;
43    delete m_rcEnc;
44}
45
46HostConnection *HostConnection::get()
47{
48    /* TODO: Make this configurable with a system property */
49    const int useQemuPipe = USE_QEMU_PIPE;
50
51    // Get thread info
52    EGLThreadInfo *tinfo = getEGLThreadInfo();
53    if (!tinfo) {
54        return NULL;
55    }
56
57    if (tinfo->hostConn == NULL) {
58        HostConnection *con = new HostConnection();
59        if (NULL == con) {
60            return NULL;
61        }
62
63        if (useQemuPipe) {
64            QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE);
65            if (!stream) {
66                ALOGE("Failed to create QemuPipeStream for host connection!!!\n");
67                delete con;
68                return NULL;
69            }
70            if (stream->connect() < 0) {
71                ALOGE("Failed to connect to host (QemuPipeStream)!!!\n");
72                delete stream;
73                delete con;
74                return NULL;
75            }
76            con->m_stream = stream;
77        }
78        else /* !useQemuPipe */
79        {
80            TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
81            if (!stream) {
82                ALOGE("Failed to create TcpStream for host connection!!!\n");
83                delete con;
84                return NULL;
85            }
86
87            if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) {
88                ALOGE("Failed to connect to host (TcpStream)!!!\n");
89                delete stream;
90                delete con;
91                return NULL;
92            }
93            con->m_stream = stream;
94        }
95
96        // send zero 'clientFlags' to the host.
97        unsigned int *pClientFlags =
98                (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int));
99        *pClientFlags = 0;
100        con->m_stream->commitBuffer(sizeof(unsigned int));
101
102        ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid());
103        tinfo->hostConn = con;
104    }
105
106    return tinfo->hostConn;
107}
108
109GLEncoder *HostConnection::glEncoder()
110{
111    if (!m_glEnc) {
112        m_glEnc = new GLEncoder(m_stream);
113        DBG("HostConnection::glEncoder new encoder %p, tid %d", m_glEnc, gettid());
114        m_glEnc->setContextAccessor(s_getGLContext);
115    }
116    return m_glEnc;
117}
118
119GL2Encoder *HostConnection::gl2Encoder()
120{
121    if (!m_gl2Enc) {
122        m_gl2Enc = new GL2Encoder(m_stream);
123        DBG("HostConnection::gl2Encoder new encoder %p, tid %d", m_gl2Enc, gettid());
124        m_gl2Enc->setContextAccessor(s_getGL2Context);
125    }
126    return m_gl2Enc;
127}
128
129renderControl_encoder_context_t *HostConnection::rcEncoder()
130{
131    if (!m_rcEnc) {
132        m_rcEnc = new renderControl_encoder_context_t(m_stream);
133    }
134    return m_rcEnc;
135}
136
137gl_client_context_t *HostConnection::s_getGLContext()
138{
139    EGLThreadInfo *ti = getEGLThreadInfo();
140    if (ti->hostConn) {
141        return ti->hostConn->m_glEnc;
142    }
143    return NULL;
144}
145
146gl2_client_context_t *HostConnection::s_getGL2Context()
147{
148    EGLThreadInfo *ti = getEGLThreadInfo();
149    if (ti->hostConn) {
150        return ti->hostConn->m_gl2Enc;
151    }
152    return NULL;
153}
154