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 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 44 HostConnection::~HostConnection() 45 { 46 delete m_stream; 47 delete m_glEnc; 48 delete m_gl2Enc; 49 delete m_rcEnc; 50 } 51 52 HostConnection *HostConnection::get() { 53 return getWithThreadInfo(getEGLThreadInfo()); 54 } 55 56 HostConnection *HostConnection::getWithThreadInfo(EGLThreadInfo* tinfo) { 57 58 /* TODO: Make this configurable with a system property */ 59 const int useQemuPipe = USE_QEMU_PIPE; 60 61 // Get thread info 62 if (!tinfo) { 63 return NULL; 64 } 65 66 if (tinfo->hostConn == NULL) { 67 HostConnection *con = new HostConnection(); 68 if (NULL == con) { 69 return NULL; 70 } 71 72 if (useQemuPipe) { 73 QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE); 74 if (!stream) { 75 ALOGE("Failed to create QemuPipeStream for host connection!!!\n"); 76 delete con; 77 return NULL; 78 } 79 if (stream->connect() < 0) { 80 ALOGE("Failed to connect to host (QemuPipeStream)!!!\n"); 81 delete stream; 82 delete con; 83 return NULL; 84 } 85 con->m_stream = stream; 86 con->m_pipeFd = stream->getSocket(); 87 } 88 else /* !useQemuPipe */ 89 { 90 TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE); 91 if (!stream) { 92 ALOGE("Failed to create TcpStream for host connection!!!\n"); 93 delete con; 94 return NULL; 95 } 96 97 if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) { 98 ALOGE("Failed to connect to host (TcpStream)!!!\n"); 99 delete stream; 100 delete con; 101 return NULL; 102 } 103 con->m_stream = stream; 104 } 105 106 // send zero 'clientFlags' to the host. 107 unsigned int *pClientFlags = 108 (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int)); 109 *pClientFlags = 0; 110 con->m_stream->commitBuffer(sizeof(unsigned int)); 111 112 ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid()); 113 tinfo->hostConn = con; 114 } 115 116 return tinfo->hostConn; 117 } 118 119 void HostConnection::exit() { 120 EGLThreadInfo *tinfo = getEGLThreadInfo(); 121 if (!tinfo) { 122 return; 123 } 124 125 if (tinfo->hostConn) { 126 delete tinfo->hostConn; 127 tinfo->hostConn = NULL; 128 } 129 } 130 131 132 133 GLEncoder *HostConnection::glEncoder() 134 { 135 if (!m_glEnc) { 136 m_glEnc = new GLEncoder(m_stream, checksumHelper()); 137 DBG("HostConnection::glEncoder new encoder %p, tid %d", m_glEnc, gettid()); 138 m_glEnc->setContextAccessor(s_getGLContext); 139 } 140 return m_glEnc; 141 } 142 143 GL2Encoder *HostConnection::gl2Encoder() 144 { 145 if (!m_gl2Enc) { 146 m_gl2Enc = new GL2Encoder(m_stream, checksumHelper()); 147 DBG("HostConnection::gl2Encoder new encoder %p, tid %d", m_gl2Enc, gettid()); 148 m_gl2Enc->setContextAccessor(s_getGL2Context); 149 } 150 return m_gl2Enc; 151 } 152 153 ExtendedRCEncoderContext *HostConnection::rcEncoder() 154 { 155 if (!m_rcEnc) { 156 m_rcEnc = new ExtendedRCEncoderContext(m_stream, checksumHelper()); 157 setChecksumHelper(m_rcEnc); 158 queryAndSetSyncImpl(m_rcEnc); 159 queryAndSetDmaImpl(m_rcEnc); 160 queryAndSetGLESMaxVersion(m_rcEnc); 161 processPipeInit(m_rcEnc); 162 } 163 return m_rcEnc; 164 } 165 166 gl_client_context_t *HostConnection::s_getGLContext() 167 { 168 EGLThreadInfo *ti = getEGLThreadInfo(); 169 if (ti->hostConn) { 170 return ti->hostConn->m_glEnc; 171 } 172 return NULL; 173 } 174 175 gl2_client_context_t *HostConnection::s_getGL2Context() 176 { 177 EGLThreadInfo *ti = getEGLThreadInfo(); 178 if (ti->hostConn) { 179 return ti->hostConn->m_gl2Enc; 180 } 181 return NULL; 182 } 183 184 const std::string& HostConnection::queryGLExtensions(ExtendedRCEncoderContext *rcEnc) { 185 if (!m_glExtensions.empty()) { 186 return m_glExtensions; 187 } 188 189 // Extensions strings are usually quite long, preallocate enough here. 190 std::string extensions_buffer(1023, '\0'); 191 192 // rcGetGLString() returns required size including the 0-terminator, so 193 // account it when passing/using the sizes. 194 int extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, 195 &extensions_buffer[0], 196 extensions_buffer.size() + 1); 197 if (extensionSize < 0) { 198 extensions_buffer.resize(-extensionSize); 199 extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, 200 &extensions_buffer[0], 201 -extensionSize + 1); 202 } 203 204 if (extensionSize > 0) { 205 extensions_buffer.resize(extensionSize - 1); 206 m_glExtensions.swap(extensions_buffer); 207 } 208 209 return m_glExtensions; 210 } 211 212 void HostConnection::setChecksumHelper(ExtendedRCEncoderContext *rcEnc) { 213 const std::string& glExtensions = queryGLExtensions(rcEnc); 214 // check the host supported version 215 uint32_t checksumVersion = 0; 216 const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix(); 217 const char* glProtocolStr = strstr(glExtensions.c_str(), checksumPrefix); 218 if (glProtocolStr) { 219 uint32_t maxVersion = ChecksumCalculator::getMaxVersion(); 220 sscanf(glProtocolStr+strlen(checksumPrefix), "%d", &checksumVersion); 221 if (maxVersion < checksumVersion) { 222 checksumVersion = maxVersion; 223 } 224 // The ordering of the following two commands matters! 225 // Must tell the host first before setting it in the guest 226 rcEnc->rcSelectChecksumHelper(rcEnc, checksumVersion, 0); 227 m_checksumHelper.setVersion(checksumVersion); 228 } 229 } 230 231 void HostConnection::queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc) { 232 const std::string& glExtensions = queryGLExtensions(rcEnc); 233 #if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__)) 234 rcEnc->setSyncImpl(SYNC_IMPL_NONE); 235 #else 236 if (glExtensions.find(kRCNativeSync) != std::string::npos) { 237 rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC); 238 } else { 239 rcEnc->setSyncImpl(SYNC_IMPL_NONE); 240 } 241 #endif 242 } 243 244 void HostConnection::queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc) { 245 std::string glExtensions = queryGLExtensions(rcEnc); 246 #if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__)) 247 rcEnc->setDmaImpl(DMA_IMPL_NONE); 248 #else 249 if (glExtensions.find(kDmaExtStr_v1) != std::string::npos) { 250 rcEnc->setDmaImpl(DMA_IMPL_v1); 251 } else { 252 rcEnc->setDmaImpl(DMA_IMPL_NONE); 253 } 254 #endif 255 } 256 257 void HostConnection::queryAndSetGLESMaxVersion(ExtendedRCEncoderContext* rcEnc) { 258 std::string glExtensions = queryGLExtensions(rcEnc); 259 if (glExtensions.find(kGLESMaxVersion_2) != std::string::npos) { 260 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2); 261 } else if (glExtensions.find(kGLESMaxVersion_3_0) != std::string::npos) { 262 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_0); 263 } else if (glExtensions.find(kGLESMaxVersion_3_1) != std::string::npos) { 264 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_1); 265 } else if (glExtensions.find(kGLESMaxVersion_3_2) != std::string::npos) { 266 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_2); 267 } else { 268 ALOGW("Unrecognized GLES max version string in extensions: %s", 269 glExtensions.c_str()); 270 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2); 271 } 272 } 273