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 #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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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