2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include "HostConnection.h"
18 #include "GLEncoder.h"
19 #include "GL2Encoder.h"
20 #include "ProcessPipe.h"
21 #include "QemuPipeStream.h"
22 #include "TcpStream.h"
23 #include "ThreadInfo.h"
25 #include <cutils/log.h>
27 #define STREAM_BUFFER_SIZE (4*1024*1024)
28 #define STREAM_PORT_NUM 22468
30 /* Set to 1 to use a QEMU pipe, or 0 for a TCP connection */
31 #define USE_QEMU_PIPE 1
33 HostConnection::HostConnection() :
44 HostConnection::~HostConnection()
52 HostConnection *HostConnection::get() {
54 /* TODO: Make this configurable with a system property */
55 const int useQemuPipe = USE_QEMU_PIPE;
58 EGLThreadInfo *tinfo = getEGLThreadInfo();
63 if (tinfo->hostConn == NULL) {
64 HostConnection *con = new HostConnection();
70 QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE);
72 ALOGE("Failed to create QemuPipeStream for host connection!!!\n");
76 if (stream->connect() < 0) {
77 ALOGE("Failed to connect to host (QemuPipeStream)!!!\n");
82 con->m_stream = stream;
83 con->m_pipeFd = stream->getSocket();
85 else /* !useQemuPipe */
87 TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
89 ALOGE("Failed to create TcpStream for host connection!!!\n");
94 if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) {
95 ALOGE("Failed to connect to host (TcpStream)!!!\n");
100 con->m_stream = stream;
103 // send zero 'clientFlags' to the host.
104 unsigned int *pClientFlags =
105 (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int));
107 con->m_stream->commitBuffer(sizeof(unsigned int));
109 ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid());
110 tinfo->hostConn = con;
113 return tinfo->hostConn;
116 void HostConnection::exit() {
117 EGLThreadInfo *tinfo = getEGLThreadInfo();
122 if (tinfo->hostConn) {
123 delete tinfo->hostConn;
124 tinfo->hostConn = NULL;
130 GLEncoder *HostConnection::glEncoder()
133 m_glEnc = new GLEncoder(m_stream, checksumHelper());
134 DBG("HostConnection::glEncoder new encoder %p, tid %d", m_glEnc, gettid());
135 m_glEnc->setContextAccessor(s_getGLContext);
140 GL2Encoder *HostConnection::gl2Encoder()
143 m_gl2Enc = new GL2Encoder(m_stream, checksumHelper());
144 DBG("HostConnection::gl2Encoder new encoder %p, tid %d", m_gl2Enc, gettid());
145 m_gl2Enc->setContextAccessor(s_getGL2Context);
150 ExtendedRCEncoderContext *HostConnection::rcEncoder()
153 m_rcEnc = new ExtendedRCEncoderContext(m_stream, checksumHelper());
154 setChecksumHelper(m_rcEnc);
155 queryAndSetSyncImpl(m_rcEnc);
156 queryAndSetDmaImpl(m_rcEnc);
157 processPipeInit(m_rcEnc);
162 gl_client_context_t *HostConnection::s_getGLContext()
164 EGLThreadInfo *ti = getEGLThreadInfo();
166 return ti->hostConn->m_glEnc;
171 gl2_client_context_t *HostConnection::s_getGL2Context()
173 EGLThreadInfo *ti = getEGLThreadInfo();
175 return ti->hostConn->m_gl2Enc;
180 const std::string& HostConnection::queryGLExtensions(ExtendedRCEncoderContext *rcEnc) {
181 if (!m_glExtensions.empty()) {
182 return m_glExtensions;
185 // Extensions strings are usually quite long, preallocate enough here.
186 std::string extensions_buffer(1023, '\0');
188 // rcGetGLString() returns required size including the 0-terminator, so
189 // account it when passing/using the sizes.
190 int extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS,
191 &extensions_buffer[0],
192 extensions_buffer.size() + 1);
193 if (extensionSize < 0) {
194 extensions_buffer.resize(-extensionSize);
195 extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS,
196 &extensions_buffer[0],
200 if (extensionSize > 0) {
201 extensions_buffer.resize(extensionSize - 1);
202 m_glExtensions.swap(extensions_buffer);
205 return m_glExtensions;
208 void HostConnection::setChecksumHelper(ExtendedRCEncoderContext *rcEnc) {
209 const std::string& glExtensions = queryGLExtensions(rcEnc);
210 // check the host supported version
211 uint32_t checksumVersion = 0;
212 const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix();
213 const char* glProtocolStr = strstr(glExtensions.c_str(), checksumPrefix);
215 uint32_t maxVersion = ChecksumCalculator::getMaxVersion();
216 sscanf(glProtocolStr+strlen(checksumPrefix), "%d", &checksumVersion);
217 if (maxVersion < checksumVersion) {
218 checksumVersion = maxVersion;
220 // The ordering of the following two commands matters!
221 // Must tell the host first before setting it in the guest
222 rcEnc->rcSelectChecksumHelper(rcEnc, checksumVersion, 0);
223 m_checksumHelper.setVersion(checksumVersion);
227 void HostConnection::queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc) {
228 const std::string& glExtensions = queryGLExtensions(rcEnc);
229 #if PLATFORM_SDK_VERSION <= 16 || PLATFORM_SDK_VERSION >= 25 || ((!defined(__i386__) && !defined(__x86_64__)))
230 rcEnc->setSyncImpl(SYNC_IMPL_NONE);
232 if (glExtensions.find(kRCNativeSync) != std::string::npos) {
233 rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC);
235 rcEnc->setSyncImpl(SYNC_IMPL_NONE);
240 void HostConnection::queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc) {
241 std::string glExtensions = queryGLExtensions(rcEnc);
242 #if PLATFORM_SDK_VERSION <= 16 || PLATFORM_SDK_VERSION >= 25 || ((!defined(__i386__) && !defined(__x86_64__)))
243 rcEnc->setDmaImpl(DMA_IMPL_NONE);
245 if (glExtensions.find(kDmaExtStr_v1) != std::string::npos) {
246 rcEnc->setDmaImpl(DMA_IMPL_v1);
248 rcEnc->setDmaImpl(DMA_IMPL_NONE);