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