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 #ifdef GOLDFISH_NO_GL 19 struct gl_client_context_t { 20 int placeholder; 21 }; 22 class GLEncoder : public gl_client_context_t { 23 public: 24 GLEncoder(IOStream*, ChecksumCalculator*) { } 25 void setContextAccessor(gl_client_context_t *()) { } 26 }; 27 struct gl2_client_context_t { 28 int placeholder; 29 }; 30 class GL2Encoder : public gl2_client_context_t { 31 public: 32 GL2Encoder(IOStream*, ChecksumCalculator*) { } 33 void setContextAccessor(gl2_client_context_t *()) { } 34 void setNoHostError(bool) { } 35 }; 36 #else 37 #include "GLEncoder.h" 38 #include "GL2Encoder.h" 39 #endif 40 41 #ifdef GOLDFISH_VULKAN 42 #include "VkEncoder.h" 43 #else 44 namespace goldfish_vk { 45 struct VkEncoder { 46 VkEncoder(IOStream*) { } 47 int placeholder; 48 }; 49 } // namespace goldfish_vk 50 #endif 51 52 using goldfish_vk::VkEncoder; 53 54 #include "ProcessPipe.h" 55 #include "QemuPipeStream.h" 56 #include "TcpStream.h" 57 #include "ThreadInfo.h" 58 59 #include "gralloc_cb.h" 60 61 #ifdef VIRTIO_GPU 62 #include "VirtioGpuStream.h" 63 #endif 64 65 #if PLATFORM_SDK_VERSION < 26 66 #include <cutils/log.h> 67 #else 68 #include <log/log.h> 69 #endif 70 71 #define STREAM_BUFFER_SIZE (4*1024*1024) 72 #define STREAM_PORT_NUM 22468 73 74 enum HostConnectionType { 75 HOST_CONNECTION_TCP = 0, 76 HOST_CONNECTION_QEMU_PIPE = 1, 77 HOST_CONNECTION_VIRTIO_GPU = 2, 78 }; 79 80 class GoldfishGralloc : public Gralloc 81 { 82 public: 83 uint32_t getHostHandle(native_handle_t const* handle) 84 { 85 return ((cb_handle_t *)handle)->hostHandle; 86 } 87 88 int getFormat(native_handle_t const* handle) 89 { 90 return ((cb_handle_t *)handle)->format; 91 } 92 }; 93 94 class GoldfishProcessPipe : public ProcessPipe 95 { 96 public: 97 bool processPipeInit(renderControl_encoder_context_t *rcEnc) 98 { 99 return ::processPipeInit(rcEnc); 100 } 101 }; 102 103 static GoldfishGralloc m_goldfishGralloc; 104 static GoldfishProcessPipe m_goldfishProcessPipe; 105 106 HostConnection::HostConnection() : 107 m_stream(NULL), 108 m_glEnc(NULL), 109 m_gl2Enc(NULL), 110 m_vkEnc(NULL), 111 m_rcEnc(NULL), 112 m_checksumHelper(), 113 m_glExtensions(), 114 m_grallocOnly(true), 115 m_noHostError(false) 116 { 117 } 118 119 HostConnection::~HostConnection() 120 { 121 delete m_stream; 122 delete m_glEnc; 123 delete m_gl2Enc; 124 delete m_rcEnc; 125 } 126 127 // static 128 HostConnection* HostConnection::connect(HostConnection* con) { 129 if (!con) return con; 130 131 const enum HostConnectionType connType = HOST_CONNECTION_VIRTIO_GPU; 132 133 switch (connType) { 134 default: 135 case HOST_CONNECTION_QEMU_PIPE: { 136 QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE); 137 if (!stream) { 138 ALOGE("Failed to create QemuPipeStream for host connection!!!\n"); 139 delete con; 140 return NULL; 141 } 142 if (stream->connect() < 0) { 143 ALOGE("Failed to connect to host (QemuPipeStream)!!!\n"); 144 delete stream; 145 delete con; 146 return NULL; 147 } 148 con->m_stream = stream; 149 con->m_grallocHelper = &m_goldfishGralloc; 150 con->m_processPipe = &m_goldfishProcessPipe; 151 break; 152 } 153 case HOST_CONNECTION_TCP: { 154 TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE); 155 if (!stream) { 156 ALOGE("Failed to create TcpStream for host connection!!!\n"); 157 delete con; 158 return NULL; 159 } 160 161 if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) { 162 ALOGE("Failed to connect to host (TcpStream)!!!\n"); 163 delete stream; 164 delete con; 165 return NULL; 166 } 167 con->m_stream = stream; 168 con->m_grallocHelper = &m_goldfishGralloc; 169 con->m_processPipe = &m_goldfishProcessPipe; 170 break; 171 } 172 #ifdef VIRTIO_GPU 173 case HOST_CONNECTION_VIRTIO_GPU: { 174 VirtioGpuStream *stream = new VirtioGpuStream(STREAM_BUFFER_SIZE); 175 if (!stream) { 176 ALOGE("Failed to create VirtioGpu for host connection!!!\n"); 177 delete con; 178 return NULL; 179 } 180 if (stream->connect() < 0) { 181 ALOGE("Failed to connect to host (VirtioGpu)!!!\n"); 182 delete stream; 183 delete con; 184 return NULL; 185 } 186 con->m_stream = stream; 187 con->m_grallocHelper = stream->getGralloc(); 188 con->m_processPipe = stream->getProcessPipe(); 189 break; 190 } 191 #endif 192 } 193 194 // send zero 'clientFlags' to the host. 195 unsigned int *pClientFlags = 196 (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int)); 197 *pClientFlags = 0; 198 con->m_stream->commitBuffer(sizeof(unsigned int)); 199 200 ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n", 201 con, getCurrentThreadId()); 202 return con; 203 } 204 205 HostConnection *HostConnection::get() { 206 return getWithThreadInfo(getEGLThreadInfo()); 207 } 208 209 HostConnection *HostConnection::getWithThreadInfo(EGLThreadInfo* tinfo) { 210 211 /* TODO: Make this configurable with a system property */ 212 const enum HostConnectionType connType = HOST_CONNECTION_VIRTIO_GPU; 213 214 // Get thread info 215 if (!tinfo) { 216 return NULL; 217 } 218 219 if (tinfo->hostConn == NULL) { 220 HostConnection *con = new HostConnection(); 221 con = connect(con); 222 223 tinfo->hostConn = con; 224 } 225 226 return tinfo->hostConn; 227 } 228 229 void HostConnection::exit() { 230 EGLThreadInfo *tinfo = getEGLThreadInfo(); 231 if (!tinfo) { 232 return; 233 } 234 235 if (tinfo->hostConn) { 236 delete tinfo->hostConn; 237 tinfo->hostConn = NULL; 238 } 239 } 240 241 // static 242 HostConnection *HostConnection::createUnique() { 243 ALOGD("%s: call\n", __func__); 244 return connect(new HostConnection()); 245 } 246 247 // static 248 void HostConnection::teardownUnique(HostConnection* con) { 249 delete con; 250 } 251 252 GLEncoder *HostConnection::glEncoder() 253 { 254 if (!m_glEnc) { 255 m_glEnc = new GLEncoder(m_stream, checksumHelper()); 256 DBG("HostConnection::glEncoder new encoder %p, tid %d", 257 m_glEnc, getCurrentThreadId()); 258 m_glEnc->setContextAccessor(s_getGLContext); 259 } 260 return m_glEnc; 261 } 262 263 GL2Encoder *HostConnection::gl2Encoder() 264 { 265 if (!m_gl2Enc) { 266 m_gl2Enc = new GL2Encoder(m_stream, checksumHelper()); 267 DBG("HostConnection::gl2Encoder new encoder %p, tid %d", 268 m_gl2Enc, getCurrentThreadId()); 269 m_gl2Enc->setContextAccessor(s_getGL2Context); 270 m_gl2Enc->setNoHostError(m_noHostError); 271 } 272 return m_gl2Enc; 273 } 274 275 VkEncoder *HostConnection::vkEncoder() 276 { 277 if (!m_vkEnc) { 278 m_vkEnc = new VkEncoder(m_stream); 279 } 280 return m_vkEnc; 281 } 282 283 ExtendedRCEncoderContext *HostConnection::rcEncoder() 284 { 285 if (!m_rcEnc) { 286 m_rcEnc = new ExtendedRCEncoderContext(m_stream, checksumHelper()); 287 setChecksumHelper(m_rcEnc); 288 queryAndSetSyncImpl(m_rcEnc); 289 queryAndSetDmaImpl(m_rcEnc); 290 queryAndSetGLESMaxVersion(m_rcEnc); 291 queryAndSetNoErrorState(m_rcEnc); 292 queryAndSetHostCompositionImpl(m_rcEnc); 293 queryAndSetDirectMemSupport(m_rcEnc); 294 queryAndSetVulkanSupport(m_rcEnc); 295 if (m_processPipe) { 296 m_processPipe->processPipeInit(m_rcEnc); 297 } 298 } 299 return m_rcEnc; 300 } 301 302 gl_client_context_t *HostConnection::s_getGLContext() 303 { 304 EGLThreadInfo *ti = getEGLThreadInfo(); 305 if (ti->hostConn) { 306 return ti->hostConn->m_glEnc; 307 } 308 return NULL; 309 } 310 311 gl2_client_context_t *HostConnection::s_getGL2Context() 312 { 313 EGLThreadInfo *ti = getEGLThreadInfo(); 314 if (ti->hostConn) { 315 return ti->hostConn->m_gl2Enc; 316 } 317 return NULL; 318 } 319 320 const std::string& HostConnection::queryGLExtensions(ExtendedRCEncoderContext *rcEnc) { 321 if (!m_glExtensions.empty()) { 322 return m_glExtensions; 323 } 324 325 // Extensions strings are usually quite long, preallocate enough here. 326 std::string extensions_buffer(1023, '\0'); 327 328 // rcGetGLString() returns required size including the 0-terminator, so 329 // account it when passing/using the sizes. 330 int extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, 331 &extensions_buffer[0], 332 extensions_buffer.size() + 1); 333 if (extensionSize < 0) { 334 extensions_buffer.resize(-extensionSize); 335 extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, 336 &extensions_buffer[0], 337 -extensionSize + 1); 338 } 339 340 if (extensionSize > 0) { 341 extensions_buffer.resize(extensionSize - 1); 342 m_glExtensions.swap(extensions_buffer); 343 } 344 345 return m_glExtensions; 346 } 347 348 void HostConnection::queryAndSetHostCompositionImpl(ExtendedRCEncoderContext *rcEnc) { 349 const std::string& glExtensions = queryGLExtensions(rcEnc); 350 ALOGD("HostComposition ext %s", glExtensions.c_str()); 351 if (glExtensions.find(kHostCompositionV1) != std::string::npos) { 352 rcEnc->setHostComposition(HOST_COMPOSITION_V1); 353 } 354 else { 355 rcEnc->setHostComposition(HOST_COMPOSITION_NONE); 356 } 357 } 358 359 void HostConnection::setChecksumHelper(ExtendedRCEncoderContext *rcEnc) { 360 const std::string& glExtensions = queryGLExtensions(rcEnc); 361 // check the host supported version 362 uint32_t checksumVersion = 0; 363 const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix(); 364 const char* glProtocolStr = strstr(glExtensions.c_str(), checksumPrefix); 365 if (glProtocolStr) { 366 uint32_t maxVersion = ChecksumCalculator::getMaxVersion(); 367 sscanf(glProtocolStr+strlen(checksumPrefix), "%d", &checksumVersion); 368 if (maxVersion < checksumVersion) { 369 checksumVersion = maxVersion; 370 } 371 // The ordering of the following two commands matters! 372 // Must tell the host first before setting it in the guest 373 rcEnc->rcSelectChecksumHelper(rcEnc, checksumVersion, 0); 374 m_checksumHelper.setVersion(checksumVersion); 375 } 376 } 377 378 void HostConnection::queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc) { 379 const std::string& glExtensions = queryGLExtensions(rcEnc); 380 #if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__)) 381 rcEnc->setSyncImpl(SYNC_IMPL_NONE); 382 #else 383 if (glExtensions.find(kRCNativeSyncV3) != std::string::npos) { 384 rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V3); 385 } else if (glExtensions.find(kRCNativeSyncV2) != std::string::npos) { 386 rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V2); 387 } else { 388 rcEnc->setSyncImpl(SYNC_IMPL_NONE); 389 } 390 #endif 391 } 392 393 void HostConnection::queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc) { 394 std::string glExtensions = queryGLExtensions(rcEnc); 395 #if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__)) 396 rcEnc->setDmaImpl(DMA_IMPL_NONE); 397 #else 398 if (glExtensions.find(kDmaExtStr_v1) != std::string::npos) { 399 rcEnc->setDmaImpl(DMA_IMPL_v1); 400 } else { 401 rcEnc->setDmaImpl(DMA_IMPL_NONE); 402 } 403 #endif 404 } 405 406 void HostConnection::queryAndSetGLESMaxVersion(ExtendedRCEncoderContext* rcEnc) { 407 std::string glExtensions = queryGLExtensions(rcEnc); 408 if (glExtensions.find(kGLESMaxVersion_2) != std::string::npos) { 409 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2); 410 } else if (glExtensions.find(kGLESMaxVersion_3_0) != std::string::npos) { 411 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_0); 412 } else if (glExtensions.find(kGLESMaxVersion_3_1) != std::string::npos) { 413 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_1); 414 } else if (glExtensions.find(kGLESMaxVersion_3_2) != std::string::npos) { 415 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_2); 416 } else { 417 ALOGW("Unrecognized GLES max version string in extensions: %s", 418 glExtensions.c_str()); 419 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2); 420 } 421 } 422 423 void HostConnection::queryAndSetNoErrorState(ExtendedRCEncoderContext* rcEnc) { 424 std::string glExtensions = queryGLExtensions(rcEnc); 425 if (glExtensions.find(kGLESNoHostError) != std::string::npos) { 426 m_noHostError = true; 427 } 428 } 429 430 void HostConnection::queryAndSetDirectMemSupport(ExtendedRCEncoderContext* rcEnc) { 431 std::string glExtensions = queryGLExtensions(rcEnc); 432 if (glExtensions.find(kGLDirectMem) != std::string::npos) { 433 rcEnc->featureInfo()->hasDirectMem = true; 434 } 435 } 436 437 void HostConnection::queryAndSetVulkanSupport(ExtendedRCEncoderContext* rcEnc) { 438 std::string glExtensions = queryGLExtensions(rcEnc); 439 if (glExtensions.find(kVulkan) != std::string::npos) { 440 rcEnc->featureInfo()->hasVulkan = true; 441 } 442 } 443 444 void HostConnection::queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext* rcEnc) { 445 std::string glExtensions = queryGLExtensions(rcEnc); 446 if (glExtensions.find(kDeferredVulkanCommands) != std::string::npos) { 447 rcEnc->featureInfo()->hasDeferredVulkanCommands = true; 448 } 449 } 450