• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 #include "GLEncoder.h"
19 #include "GL2Encoder.h"
20 #include "ProcessPipe.h"
21 #include "QemuPipeStream.h"
22 #include "TcpStream.h"
23 #include "ThreadInfo.h"
24 
25 #include <cutils/log.h>
26 
27 #define STREAM_BUFFER_SIZE  (4*1024*1024)
28 #define STREAM_PORT_NUM     22468
29 
30 /* Set to 1 to use a QEMU pipe, or 0 for a TCP connection */
31 #define  USE_QEMU_PIPE  1
32 
HostConnection()33 HostConnection::HostConnection() :
34     m_stream(NULL),
35     m_glEnc(NULL),
36     m_gl2Enc(NULL),
37     m_rcEnc(NULL),
38     m_checksumHelper(),
39     m_glExtensions(),
40     m_grallocOnly(true)
41 {
42 }
43 
~HostConnection()44 HostConnection::~HostConnection()
45 {
46     delete m_stream;
47     delete m_glEnc;
48     delete m_gl2Enc;
49     delete m_rcEnc;
50 }
51 
get()52 HostConnection *HostConnection::get() {
53 
54     /* TODO: Make this configurable with a system property */
55     const int useQemuPipe = USE_QEMU_PIPE;
56 
57     // Get thread info
58     EGLThreadInfo *tinfo = getEGLThreadInfo();
59     if (!tinfo) {
60         return NULL;
61     }
62 
63     if (tinfo->hostConn == NULL) {
64         HostConnection *con = new HostConnection();
65         if (NULL == con) {
66             return NULL;
67         }
68 
69         if (useQemuPipe) {
70             QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE);
71             if (!stream) {
72                 ALOGE("Failed to create QemuPipeStream for host connection!!!\n");
73                 delete con;
74                 return NULL;
75             }
76             if (stream->connect() < 0) {
77                 ALOGE("Failed to connect to host (QemuPipeStream)!!!\n");
78                 delete stream;
79                 delete con;
80                 return NULL;
81             }
82             con->m_stream = stream;
83         }
84         else /* !useQemuPipe */
85         {
86             TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
87             if (!stream) {
88                 ALOGE("Failed to create TcpStream for host connection!!!\n");
89                 delete con;
90                 return NULL;
91             }
92 
93             if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) {
94                 ALOGE("Failed to connect to host (TcpStream)!!!\n");
95                 delete stream;
96                 delete con;
97                 return NULL;
98             }
99             con->m_stream = stream;
100         }
101 
102         // send zero 'clientFlags' to the host.
103         unsigned int *pClientFlags =
104                 (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int));
105         *pClientFlags = 0;
106         con->m_stream->commitBuffer(sizeof(unsigned int));
107 
108         ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid());
109         tinfo->hostConn = con;
110     }
111 
112     return tinfo->hostConn;
113 }
114 
exit()115 void HostConnection::exit() {
116     EGLThreadInfo *tinfo = getEGLThreadInfo();
117     if (!tinfo) {
118         return;
119     }
120 
121     if (tinfo->hostConn) {
122         delete tinfo->hostConn;
123         tinfo->hostConn = NULL;
124     }
125 }
126 
127 
128 
glEncoder()129 GLEncoder *HostConnection::glEncoder()
130 {
131     if (!m_glEnc) {
132         m_glEnc = new GLEncoder(m_stream, checksumHelper());
133         DBG("HostConnection::glEncoder new encoder %p, tid %d", m_glEnc, gettid());
134         m_glEnc->setContextAccessor(s_getGLContext);
135     }
136     return m_glEnc;
137 }
138 
gl2Encoder()139 GL2Encoder *HostConnection::gl2Encoder()
140 {
141     if (!m_gl2Enc) {
142         m_gl2Enc = new GL2Encoder(m_stream, checksumHelper());
143         DBG("HostConnection::gl2Encoder new encoder %p, tid %d", m_gl2Enc, gettid());
144         m_gl2Enc->setContextAccessor(s_getGL2Context);
145     }
146     return m_gl2Enc;
147 }
148 
rcEncoder()149 ExtendedRCEncoderContext *HostConnection::rcEncoder()
150 {
151     if (!m_rcEnc) {
152         m_rcEnc = new ExtendedRCEncoderContext(m_stream, checksumHelper());
153         setChecksumHelper(m_rcEnc);
154         queryAndSetSyncImpl(m_rcEnc);
155         processPipeInit(m_rcEnc);
156     }
157     return m_rcEnc;
158 }
159 
s_getGLContext()160 gl_client_context_t *HostConnection::s_getGLContext()
161 {
162     EGLThreadInfo *ti = getEGLThreadInfo();
163     if (ti->hostConn) {
164         return ti->hostConn->m_glEnc;
165     }
166     return NULL;
167 }
168 
s_getGL2Context()169 gl2_client_context_t *HostConnection::s_getGL2Context()
170 {
171     EGLThreadInfo *ti = getEGLThreadInfo();
172     if (ti->hostConn) {
173         return ti->hostConn->m_gl2Enc;
174     }
175     return NULL;
176 }
177 
queryGLExtensions(ExtendedRCEncoderContext * rcEnc)178 std::string HostConnection::queryGLExtensions(ExtendedRCEncoderContext *rcEnc) {
179     if (m_glExtensions.size() > 0) return m_glExtensions;
180 
181     std::string extensions_buffer;
182     int extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, NULL, 0);
183     if (extensionSize < 0) {
184 
185         extensions_buffer.resize(-extensionSize);
186         extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS,
187                                              &extensions_buffer[0], -extensionSize);
188 
189         if (extensionSize <= 0) {
190             return std::string();
191         }
192 
193         m_glExtensions += extensions_buffer;
194 
195         return m_glExtensions;
196     }
197 
198     return std::string();
199 }
200 
setChecksumHelper(ExtendedRCEncoderContext * rcEnc)201 void HostConnection::setChecksumHelper(ExtendedRCEncoderContext *rcEnc) {
202     std::string glExtensions = queryGLExtensions(rcEnc);
203     // check the host supported version
204     uint32_t checksumVersion = 0;
205     const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix();
206     const char* glProtocolStr = strstr(glExtensions.c_str(), checksumPrefix);
207     if (glProtocolStr) {
208         uint32_t maxVersion = ChecksumCalculator::getMaxVersion();
209         sscanf(glProtocolStr+strlen(checksumPrefix), "%d", &checksumVersion);
210         if (maxVersion < checksumVersion) {
211             checksumVersion = maxVersion;
212         }
213         // The ordering of the following two commands matters!
214         // Must tell the host first before setting it in the guest
215         rcEnc->rcSelectChecksumHelper(rcEnc, checksumVersion, 0);
216         m_checksumHelper.setVersion(checksumVersion);
217     }
218 }
219 
queryAndSetSyncImpl(ExtendedRCEncoderContext * rcEnc)220 void HostConnection::queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc) {
221     std::string glExtensions = queryGLExtensions(rcEnc);
222 #if PLATFORM_SDK_VERSION <= 16
223     rcEnc->setSyncImpl(SYNC_IMPL_NONE);
224 #else
225     if (glExtensions.find(kRCNativeSync) != std::string::npos) {
226         rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC);
227     } else {
228         rcEnc->setSyncImpl(SYNC_IMPL_NONE);
229     }
230 #endif
231 }
232