Home | History | Annotate | Download | only in OpenglSystemCommon
      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