OSDN Git Service

Fix git-master and sync device
[android-x86/device-generic-goldfish-opengl.git] / system / OpenglSystemCommon / HostConnection.cpp
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             con->m_pipeFd = stream->getSocket();
84         }
85         else /* !useQemuPipe */
86         {
87             TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
88             if (!stream) {
89                 ALOGE("Failed to create TcpStream for host connection!!!\n");
90                 delete con;
91                 return NULL;
92             }
93
94             if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) {
95                 ALOGE("Failed to connect to host (TcpStream)!!!\n");
96                 delete stream;
97                 delete con;
98                 return NULL;
99             }
100             con->m_stream = stream;
101         }
102
103         // send zero 'clientFlags' to the host.
104         unsigned int *pClientFlags =
105                 (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int));
106         *pClientFlags = 0;
107         con->m_stream->commitBuffer(sizeof(unsigned int));
108
109         ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid());
110         tinfo->hostConn = con;
111     }
112
113     return tinfo->hostConn;
114 }
115
116 void HostConnection::exit() {
117     EGLThreadInfo *tinfo = getEGLThreadInfo();
118     if (!tinfo) {
119         return;
120     }
121
122     if (tinfo->hostConn) {
123         delete tinfo->hostConn;
124         tinfo->hostConn = NULL;
125     }
126 }
127
128
129
130 GLEncoder *HostConnection::glEncoder()
131 {
132     if (!m_glEnc) {
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);
136     }
137     return m_glEnc;
138 }
139
140 GL2Encoder *HostConnection::gl2Encoder()
141 {
142     if (!m_gl2Enc) {
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);
146     }
147     return m_gl2Enc;
148 }
149
150 ExtendedRCEncoderContext *HostConnection::rcEncoder()
151 {
152     if (!m_rcEnc) {
153         m_rcEnc = new ExtendedRCEncoderContext(m_stream, checksumHelper());
154         setChecksumHelper(m_rcEnc);
155         queryAndSetSyncImpl(m_rcEnc);
156         queryAndSetDmaImpl(m_rcEnc);
157         processPipeInit(m_rcEnc);
158     }
159     return m_rcEnc;
160 }
161
162 gl_client_context_t *HostConnection::s_getGLContext()
163 {
164     EGLThreadInfo *ti = getEGLThreadInfo();
165     if (ti->hostConn) {
166         return ti->hostConn->m_glEnc;
167     }
168     return NULL;
169 }
170
171 gl2_client_context_t *HostConnection::s_getGL2Context()
172 {
173     EGLThreadInfo *ti = getEGLThreadInfo();
174     if (ti->hostConn) {
175         return ti->hostConn->m_gl2Enc;
176     }
177     return NULL;
178 }
179
180 const std::string& HostConnection::queryGLExtensions(ExtendedRCEncoderContext *rcEnc) {
181     if (!m_glExtensions.empty()) {
182         return m_glExtensions;
183     }
184
185     // Extensions strings are usually quite long, preallocate enough here.
186     std::string extensions_buffer(1023, '\0');
187
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],
197                                             -extensionSize + 1);
198     }
199
200     if (extensionSize > 0) {
201         extensions_buffer.resize(extensionSize - 1);
202         m_glExtensions.swap(extensions_buffer);
203     }
204
205     return m_glExtensions;
206 }
207
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);
214     if (glProtocolStr) {
215         uint32_t maxVersion = ChecksumCalculator::getMaxVersion();
216         sscanf(glProtocolStr+strlen(checksumPrefix), "%d", &checksumVersion);
217         if (maxVersion < checksumVersion) {
218             checksumVersion = maxVersion;
219         }
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);
224     }
225 }
226
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);
231 #else
232     if (glExtensions.find(kRCNativeSync) != std::string::npos) {
233         rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC);
234     } else {
235         rcEnc->setSyncImpl(SYNC_IMPL_NONE);
236     }
237 #endif
238 }
239
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);
244 #else
245     if (glExtensions.find(kDmaExtStr_v1) != std::string::npos) {
246         rcEnc->setDmaImpl(DMA_IMPL_v1);
247     } else {
248         rcEnc->setDmaImpl(DMA_IMPL_NONE);
249     }
250 #endif
251 }