• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "cutils/properties.h"
19 
20 #ifdef GOLDFISH_NO_GL
21 struct gl_client_context_t {
22     int placeholder;
23 };
24 class GLEncoder : public gl_client_context_t {
25 public:
GLEncoder(IOStream *,ChecksumCalculator *)26     GLEncoder(IOStream*, ChecksumCalculator*) { }
setContextAccessor(gl_client_context_t * ())27     void setContextAccessor(gl_client_context_t *()) { }
28 };
29 struct gl2_client_context_t {
30     int placeholder;
31 };
32 class GL2Encoder : public gl2_client_context_t {
33 public:
GL2Encoder(IOStream *,ChecksumCalculator *)34     GL2Encoder(IOStream*, ChecksumCalculator*) { }
setContextAccessor(gl2_client_context_t * ())35     void setContextAccessor(gl2_client_context_t *()) { }
setNoHostError(bool)36     void setNoHostError(bool) { }
setDrawCallFlushInterval(uint32_t)37     void setDrawCallFlushInterval(uint32_t) { }
setHasAsyncUnmapBuffer(int)38     void setHasAsyncUnmapBuffer(int) { }
39 };
40 #else
41 #include "GLEncoder.h"
42 #include "GL2Encoder.h"
43 #endif
44 
45 #ifdef GOLDFISH_VULKAN
46 #include "VkEncoder.h"
47 #include "AddressSpaceStream.h"
48 #else
49 namespace goldfish_vk {
50 struct VkEncoder {
VkEncodergoldfish_vk::VkEncoder51     VkEncoder(IOStream*) { }
52     int placeholder;
53 };
54 } // namespace goldfish_vk
55 class QemuPipeStream;
56 typedef QemuPipeStream AddressSpaceStream;
createAddressSpaceStream(size_t bufSize)57 AddressSpaceStream* createAddressSpaceStream(size_t bufSize) {
58     ALOGE("%s: FATAL: Trying to create ASG stream in unsupported build\n", __func__);
59     abort();
60 }
61 #endif
62 
63 using goldfish_vk::VkEncoder;
64 
65 #include "ProcessPipe.h"
66 #include "QemuPipeStream.h"
67 #include "TcpStream.h"
68 #include "ThreadInfo.h"
69 #include <gralloc_cb_bp.h>
70 
71 #ifdef VIRTIO_GPU
72 
73 #include "VirtioGpuStream.h"
74 #include "VirtioGpuPipeStream.h"
75 
76 #include <cros_gralloc_handle.h>
77 #include <drm/virtgpu_drm.h>
78 #include <xf86drm.h>
79 
80 #endif
81 
82 #undef LOG_TAG
83 #define LOG_TAG "HostConnection"
84 #if PLATFORM_SDK_VERSION < 26
85 #include <cutils/log.h>
86 #else
87 #include <log/log.h>
88 #endif
89 
90 #define STREAM_BUFFER_SIZE  (4*1024*1024)
91 #define STREAM_PORT_NUM     22468
92 
getConnectionTypeFromProperty()93 static HostConnectionType getConnectionTypeFromProperty() {
94 #ifdef __Fuchsia__
95     return HOST_CONNECTION_ADDRESS_SPACE;
96 #else
97     char transportValue[PROPERTY_VALUE_MAX] = "";
98     property_get("ro.kernel.qemu.gltransport", transportValue, "");
99 
100     bool isValid = transportValue[0] != '\0';
101 
102     if (!isValid) {
103         property_get("ro.boot.hardware.gltransport", transportValue, "");
104         isValid = transportValue[0] != '\0';
105     }
106 
107     if (!isValid) return HOST_CONNECTION_QEMU_PIPE;
108 
109     if (!strcmp("tcp", transportValue)) return HOST_CONNECTION_TCP;
110     if (!strcmp("pipe", transportValue)) return HOST_CONNECTION_QEMU_PIPE;
111     if (!strcmp("virtio-gpu", transportValue)) return HOST_CONNECTION_VIRTIO_GPU;
112     if (!strcmp("asg", transportValue)) return HOST_CONNECTION_ADDRESS_SPACE;
113     if (!strcmp("virtio-gpu-pipe", transportValue)) return HOST_CONNECTION_VIRTIO_GPU_PIPE;
114 
115     return HOST_CONNECTION_QEMU_PIPE;
116 #endif
117 }
118 
getDrawCallFlushIntervalFromProperty()119 static uint32_t getDrawCallFlushIntervalFromProperty() {
120     char flushValue[PROPERTY_VALUE_MAX] = "";
121     property_get("ro.kernel.qemu.gltransport.drawFlushInterval", flushValue, "");
122 
123     bool isValid = flushValue[0] != '\0';
124     if (!isValid) return 800;
125 
126     long interval = strtol(flushValue, 0, 10);
127 
128     if (!interval) return 800;
129 
130     return (uint32_t)interval;
131 }
132 
getGrallocTypeFromProperty()133 static GrallocType getGrallocTypeFromProperty() {
134     char prop[PROPERTY_VALUE_MAX] = "";
135     property_get("ro.hardware.gralloc", prop, "");
136 
137     bool isValid = prop[0] != '\0';
138 
139     if (!isValid) return GRALLOC_TYPE_RANCHU;
140 
141     if (!strcmp("ranchu", prop)) return GRALLOC_TYPE_RANCHU;
142     if (!strcmp("minigbm", prop)) return GRALLOC_TYPE_MINIGBM;
143     return GRALLOC_TYPE_RANCHU;
144 }
145 
146 class GoldfishGralloc : public Gralloc
147 {
148 public:
createColorBuffer(ExtendedRCEncoderContext * rcEnc,int width,int height,uint32_t glformat)149     virtual uint32_t createColorBuffer(
150         ExtendedRCEncoderContext* rcEnc,
151         int width, int height, uint32_t glformat) {
152         return rcEnc->rcCreateColorBuffer(
153             rcEnc, width, height, glformat);
154     }
155 
getHostHandle(native_handle_t const * handle)156     virtual uint32_t getHostHandle(native_handle_t const* handle)
157     {
158         return cb_handle_t::from(handle)->hostHandle;
159     }
160 
getFormat(native_handle_t const * handle)161     virtual int getFormat(native_handle_t const* handle)
162     {
163         return cb_handle_t::from(handle)->format;
164     }
165 
getAllocatedSize(native_handle_t const * handle)166     virtual size_t getAllocatedSize(native_handle_t const* handle)
167     {
168         return static_cast<size_t>(cb_handle_t::from(handle)->allocatedSize());
169     }
170 };
171 
align_up(uint32_t n,uint32_t a)172 static inline uint32_t align_up(uint32_t n, uint32_t a) {
173     return ((n + a - 1) / a) * a;
174 }
175 
176 #ifdef VIRTIO_GPU
177 
178 class MinigbmGralloc : public Gralloc {
179 public:
createColorBuffer(ExtendedRCEncoderContext *,int width,int height,uint32_t glformat)180     virtual uint32_t createColorBuffer(
181         ExtendedRCEncoderContext*,
182         int width, int height, uint32_t glformat) {
183 
184         // Only supported format for pbuffers in gfxstream
185         // should be RGBA8
186         const uint32_t kGlRGB = 0x1907;
187         const uint32_t kGlRGBA = 0x1908;
188         const uint32_t kVirglFormatRGBA = 67; // VIRGL_FORMAT_R8G8B8A8_UNORM;
189         uint32_t virtgpu_format = 0;
190         uint32_t bpp = 0;
191         switch (glformat) {
192             case kGlRGB:
193                 ALOGD("Note: egl wanted GL_RGB, still using RGBA");
194                 virtgpu_format = kVirglFormatRGBA;
195                 bpp = 4;
196                 break;
197             case kGlRGBA:
198                 virtgpu_format = kVirglFormatRGBA;
199                 bpp = 4;
200                 break;
201             default:
202                 ALOGD("Note: egl wanted 0x%x, still using RGBA", glformat);
203                 virtgpu_format = kVirglFormatRGBA;
204                 bpp = 4;
205                 break;
206         }
207         const uint32_t kPipeTexture2D = 2; // PIPE_TEXTURE_2D
208         const uint32_t kBindRenderTarget = 1 << 1; // VIRGL_BIND_RENDER_TARGET
209         struct drm_virtgpu_resource_create res_create;
210         memset(&res_create, 0, sizeof(res_create));
211         res_create.target = kPipeTexture2D;
212         res_create.format = virtgpu_format;
213         res_create.bind = kBindRenderTarget;
214         res_create.width = width;
215         res_create.height = height;
216         res_create.depth = 1;
217         res_create.array_size = 1;
218         res_create.last_level = 0;
219         res_create.nr_samples = 0;
220         res_create.stride = bpp * width;
221         res_create.size = align_up(bpp * width * height, PAGE_SIZE);
222 
223         int ret = drmIoctl(m_fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &res_create);
224         if (ret) {
225             ALOGE("%s: DRM_IOCTL_VIRTGPU_RESOURCE_CREATE failed with %s (%d)\n", __func__,
226                   strerror(errno), errno);
227             abort();
228         }
229 
230         return res_create.res_handle;
231     }
232 
getHostHandle(native_handle_t const * handle)233     virtual uint32_t getHostHandle(native_handle_t const* handle) {
234         struct drm_virtgpu_resource_info info;
235         if (!getResInfo(handle, &info)) {
236             ALOGE("%s: failed to get resource info\n", __func__);
237             return 0;
238         }
239 
240         return info.res_handle;
241     }
242 
getFormat(native_handle_t const * handle)243     virtual int getFormat(native_handle_t const* handle) {
244         return ((cros_gralloc_handle *)handle)->droid_format;
245     }
246 
getAllocatedSize(native_handle_t const * handle)247     virtual size_t getAllocatedSize(native_handle_t const* handle) {
248         struct drm_virtgpu_resource_info info;
249         if (!getResInfo(handle, &info)) {
250             ALOGE("%s: failed to get resource info\n", __func__);
251             return 0;
252         }
253 
254         return info.size;
255     }
256 
setFd(int fd)257     void setFd(int fd) { m_fd = fd; }
258 
259 private:
260 
getResInfo(native_handle_t const * handle,struct drm_virtgpu_resource_info * info)261     bool getResInfo(native_handle_t const* handle,
262                     struct drm_virtgpu_resource_info* info) {
263         memset(info, 0x0, sizeof(*info));
264         if (m_fd < 0) {
265             ALOGE("%s: Error, rendernode fd missing\n", __func__);
266             return false;
267         }
268 
269         struct drm_gem_close gem_close;
270         memset(&gem_close, 0x0, sizeof(gem_close));
271 
272         cros_gralloc_handle const* cros_handle =
273             reinterpret_cast<cros_gralloc_handle const*>(handle);
274 
275         uint32_t prime_handle;
276         int ret = drmPrimeFDToHandle(m_fd, cros_handle->fds[0], &prime_handle);
277         if (ret) {
278             ALOGE("%s: DRM_IOCTL_PRIME_FD_TO_HANDLE failed: %s (errno %d)\n",
279                   __func__, strerror(errno), errno);
280             return false;
281         }
282 
283         info->bo_handle = prime_handle;
284         gem_close.handle = prime_handle;
285 
286         ret = drmIoctl(m_fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, info);
287         if (ret) {
288             ALOGE("%s: DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed: %s (errno %d)\n",
289                   __func__, strerror(errno), errno);
290             drmIoctl(m_fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
291             return false;
292         }
293 
294         drmIoctl(m_fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
295         return true;
296     }
297 
298     int m_fd = -1;
299 };
300 
301 #else
302 
303 class MinigbmGralloc : public Gralloc {
304 public:
createColorBuffer(ExtendedRCEncoderContext *,int width,int height,uint32_t glformat)305     virtual uint32_t createColorBuffer(
306         ExtendedRCEncoderContext*,
307         int width, int height, uint32_t glformat) {
308         ALOGE("%s: Error: using minigbm without -DVIRTIO_GPU\n", __func__);
309         return 0;
310     }
311 
getHostHandle(native_handle_t const * handle)312     virtual uint32_t getHostHandle(native_handle_t const* handle) {
313         ALOGE("%s: Error: using minigbm without -DVIRTIO_GPU\n", __func__);
314         return 0;
315     }
316 
getFormat(native_handle_t const * handle)317     virtual int getFormat(native_handle_t const* handle) {
318         ALOGE("%s: Error: using minigbm without -DVIRTIO_GPU\n", __func__);
319         return 0;
320     }
321 
getAllocatedSize(native_handle_t const * handle)322     virtual size_t getAllocatedSize(native_handle_t const* handle) {
323         ALOGE("%s: Error: using minigbm without -DVIRTIO_GPU\n", __func__);
324         return 0;
325     }
326 
setFd(int fd)327     void setFd(int fd) { m_fd = fd; }
328 
329 private:
330 
331     int m_fd = -1;
332 };
333 
334 #endif
335 
336 class GoldfishProcessPipe : public ProcessPipe
337 {
338 public:
processPipeInit(HostConnectionType connType,renderControl_encoder_context_t * rcEnc)339     bool processPipeInit(HostConnectionType connType, renderControl_encoder_context_t *rcEnc)
340     {
341         return ::processPipeInit(connType, rcEnc);
342     }
343 };
344 
345 static GoldfishGralloc m_goldfishGralloc;
346 static GoldfishProcessPipe m_goldfishProcessPipe;
347 
HostConnection()348 HostConnection::HostConnection() :
349     m_stream(NULL),
350     m_glEnc(NULL),
351     m_gl2Enc(NULL),
352     m_vkEnc(NULL),
353     m_rcEnc(NULL),
354     m_checksumHelper(),
355     m_glExtensions(),
356     m_grallocOnly(true),
357     m_noHostError(false) { }
358 
~HostConnection()359 HostConnection::~HostConnection()
360 {
361     // round-trip to ensure that queued commands have been processed
362     // before process pipe closure is detected.
363     if (m_rcEnc) {
364         (void) m_rcEnc->rcGetRendererVersion(m_rcEnc);
365     }
366     if (m_grallocType == GRALLOC_TYPE_MINIGBM) {
367         delete m_grallocHelper;
368     }
369     delete m_stream;
370     delete m_glEnc;
371     delete m_gl2Enc;
372     delete m_rcEnc;
373 }
374 
375 // static
connect(HostConnection * con)376 HostConnection* HostConnection::connect(HostConnection* con) {
377     if (!con) return con;
378 
379     const enum HostConnectionType connType = getConnectionTypeFromProperty();
380     // const enum HostConnectionType connType = HOST_CONNECTION_VIRTIO_GPU;
381 
382     switch (connType) {
383         case HOST_CONNECTION_ADDRESS_SPACE: {
384             AddressSpaceStream *stream = createAddressSpaceStream(STREAM_BUFFER_SIZE);
385             if (!stream) {
386                 ALOGE("Failed to create AddressSpaceStream for host connection!!!\n");
387                 delete con;
388                 return NULL;
389             }
390             con->m_connectionType = HOST_CONNECTION_ADDRESS_SPACE;
391             con->m_grallocType = GRALLOC_TYPE_RANCHU;
392             con->m_stream = stream;
393             con->m_grallocHelper = &m_goldfishGralloc;
394             con->m_processPipe = &m_goldfishProcessPipe;
395             break;
396         }
397         case HOST_CONNECTION_QEMU_PIPE: {
398             QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE);
399             if (!stream) {
400                 ALOGE("Failed to create QemuPipeStream for host connection!!!\n");
401                 delete con;
402                 return NULL;
403             }
404             if (stream->connect() < 0) {
405                 ALOGE("Failed to connect to host (QemuPipeStream)!!!\n");
406                 delete stream;
407                 delete con;
408                 return NULL;
409             }
410             con->m_connectionType = HOST_CONNECTION_QEMU_PIPE;
411             con->m_grallocType = GRALLOC_TYPE_RANCHU;
412             con->m_stream = stream;
413             con->m_grallocHelper = &m_goldfishGralloc;
414             con->m_processPipe = &m_goldfishProcessPipe;
415             break;
416         }
417         case HOST_CONNECTION_TCP: {
418 #ifdef __Fuchsia__
419             ALOGE("Fuchsia doesn't support HOST_CONNECTION_TCP!!!\n");
420             delete con;
421             return NULL;
422             break;
423 #else
424             TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
425             if (!stream) {
426                 ALOGE("Failed to create TcpStream for host connection!!!\n");
427                 delete con;
428                 return NULL;
429             }
430 
431             if (stream->connect("10.0.2.2", STREAM_PORT_NUM) < 0) {
432                 ALOGE("Failed to connect to host (TcpStream)!!!\n");
433                 delete stream;
434                 delete con;
435                 return NULL;
436             }
437             con->m_connectionType = HOST_CONNECTION_TCP;
438             con->m_grallocType = GRALLOC_TYPE_RANCHU;
439             con->m_stream = stream;
440             con->m_grallocHelper = &m_goldfishGralloc;
441             con->m_processPipe = &m_goldfishProcessPipe;
442             break;
443 #endif
444         }
445 #ifdef VIRTIO_GPU
446         case HOST_CONNECTION_VIRTIO_GPU: {
447             VirtioGpuStream *stream = new VirtioGpuStream(STREAM_BUFFER_SIZE);
448             if (!stream) {
449                 ALOGE("Failed to create VirtioGpu for host connection!!!\n");
450                 delete con;
451                 return NULL;
452             }
453             if (stream->connect() < 0) {
454                 ALOGE("Failed to connect to host (VirtioGpu)!!!\n");
455                 delete stream;
456                 delete con;
457                 return NULL;
458             }
459             con->m_connectionType = HOST_CONNECTION_VIRTIO_GPU;
460             con->m_grallocType = GRALLOC_TYPE_MINIGBM;
461             con->m_stream = stream;
462             MinigbmGralloc* m = new MinigbmGralloc;
463             m->setFd(stream->getRendernodeFd());
464             con->m_grallocHelper = m;
465             con->m_processPipe = stream->getProcessPipe();
466             break;
467         }
468         case HOST_CONNECTION_VIRTIO_GPU_PIPE: {
469             VirtioGpuPipeStream *stream = new VirtioGpuPipeStream(STREAM_BUFFER_SIZE);
470             if (!stream) {
471                 ALOGE("Failed to create VirtioGpu for host connection!!!\n");
472                 delete con;
473                 return NULL;
474             }
475             if (stream->connect() < 0) {
476                 ALOGE("Failed to connect to host (VirtioGpu)!!!\n");
477                 delete stream;
478                 delete con;
479                 return NULL;
480             }
481             con->m_connectionType = HOST_CONNECTION_VIRTIO_GPU_PIPE;
482             con->m_grallocType = getGrallocTypeFromProperty();
483             con->m_stream = stream;
484             switch (con->m_grallocType) {
485                 case GRALLOC_TYPE_RANCHU:
486                     con->m_grallocHelper = &m_goldfishGralloc;
487                     break;
488                 case GRALLOC_TYPE_MINIGBM: {
489                     MinigbmGralloc* m = new MinigbmGralloc;
490                     m->setFd(stream->getRendernodeFd());
491                     con->m_grallocHelper = m;
492                     break;
493                 }
494                 default:
495                     ALOGE("Fatal: Unknown gralloc type 0x%x\n", con->m_grallocType);
496                     abort();
497             }
498             con->m_processPipe = &m_goldfishProcessPipe;
499             break;
500         }
501 #else
502         default:
503             break;
504 #endif
505     }
506 
507     // send zero 'clientFlags' to the host.
508     unsigned int *pClientFlags =
509             (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int));
510     *pClientFlags = 0;
511     con->m_stream->commitBuffer(sizeof(unsigned int));
512 
513     ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n",
514           con, getCurrentThreadId());
515 
516     // ALOGD("Address space echo latency check done\n");
517     return con;
518 }
519 
get()520 HostConnection *HostConnection::get() {
521     return getWithThreadInfo(getEGLThreadInfo());
522 }
523 
getWithThreadInfo(EGLThreadInfo * tinfo)524 HostConnection *HostConnection::getWithThreadInfo(EGLThreadInfo* tinfo) {
525     // Get thread info
526     if (!tinfo) {
527         return NULL;
528     }
529 
530     if (tinfo->hostConn == NULL) {
531         HostConnection *con = new HostConnection();
532         con = connect(con);
533 
534         tinfo->hostConn = con;
535     }
536 
537     return tinfo->hostConn;
538 }
539 
exit()540 void HostConnection::exit() {
541     EGLThreadInfo *tinfo = getEGLThreadInfo();
542     if (!tinfo) {
543         return;
544     }
545 
546     if (tinfo->hostConn) {
547         delete tinfo->hostConn;
548         tinfo->hostConn = NULL;
549     }
550 }
551 
552 // static
createUnique()553 HostConnection *HostConnection::createUnique() {
554     ALOGD("%s: call\n", __func__);
555     return connect(new HostConnection());
556 }
557 
558 // static
teardownUnique(HostConnection * con)559 void HostConnection::teardownUnique(HostConnection* con) {
560     delete con;
561 }
562 
glEncoder()563 GLEncoder *HostConnection::glEncoder()
564 {
565     if (!m_glEnc) {
566         m_glEnc = new GLEncoder(m_stream, checksumHelper());
567         DBG("HostConnection::glEncoder new encoder %p, tid %d",
568             m_glEnc, getCurrentThreadId());
569         m_glEnc->setContextAccessor(s_getGLContext);
570     }
571     return m_glEnc;
572 }
573 
gl2Encoder()574 GL2Encoder *HostConnection::gl2Encoder()
575 {
576     if (!m_gl2Enc) {
577         m_gl2Enc = new GL2Encoder(m_stream, checksumHelper());
578         DBG("HostConnection::gl2Encoder new encoder %p, tid %d",
579             m_gl2Enc, getCurrentThreadId());
580         m_gl2Enc->setContextAccessor(s_getGL2Context);
581         m_gl2Enc->setNoHostError(m_noHostError);
582         m_gl2Enc->setDrawCallFlushInterval(
583             getDrawCallFlushIntervalFromProperty());
584         m_gl2Enc->setHasAsyncUnmapBuffer(m_rcEnc->hasAsyncUnmapBuffer());
585     }
586     return m_gl2Enc;
587 }
588 
vkEncoder()589 VkEncoder *HostConnection::vkEncoder()
590 {
591     if (!m_vkEnc) {
592         m_vkEnc = new VkEncoder(m_stream);
593     }
594     return m_vkEnc;
595 }
596 
rcEncoder()597 ExtendedRCEncoderContext *HostConnection::rcEncoder()
598 {
599     if (!m_rcEnc) {
600         m_rcEnc = new ExtendedRCEncoderContext(m_stream, checksumHelper());
601         setChecksumHelper(m_rcEnc);
602         queryAndSetSyncImpl(m_rcEnc);
603         queryAndSetDmaImpl(m_rcEnc);
604         queryAndSetGLESMaxVersion(m_rcEnc);
605         queryAndSetNoErrorState(m_rcEnc);
606         queryAndSetHostCompositionImpl(m_rcEnc);
607         queryAndSetDirectMemSupport(m_rcEnc);
608         queryAndSetVulkanSupport(m_rcEnc);
609         queryAndSetDeferredVulkanCommandsSupport(m_rcEnc);
610         queryAndSetVulkanNullOptionalStringsSupport(m_rcEnc);
611         queryAndSetVulkanCreateResourcesWithRequirementsSupport(m_rcEnc);
612         queryAndSetVulkanIgnoredHandles(m_rcEnc);
613         queryAndSetYUVCache(m_rcEnc);
614         queryAndSetAsyncUnmapBuffer(m_rcEnc);
615         queryAndSetVirtioGpuNext(m_rcEnc);
616         queryHasSharedSlotsHostMemoryAllocator(m_rcEnc);
617         queryAndSetVulkanFreeMemorySync(m_rcEnc);
618         if (m_processPipe) {
619             m_processPipe->processPipeInit(m_connectionType, m_rcEnc);
620         }
621     }
622     return m_rcEnc;
623 }
624 
s_getGLContext()625 gl_client_context_t *HostConnection::s_getGLContext()
626 {
627     EGLThreadInfo *ti = getEGLThreadInfo();
628     if (ti->hostConn) {
629         return ti->hostConn->m_glEnc;
630     }
631     return NULL;
632 }
633 
s_getGL2Context()634 gl2_client_context_t *HostConnection::s_getGL2Context()
635 {
636     EGLThreadInfo *ti = getEGLThreadInfo();
637     if (ti->hostConn) {
638         return ti->hostConn->m_gl2Enc;
639     }
640     return NULL;
641 }
642 
queryGLExtensions(ExtendedRCEncoderContext * rcEnc)643 const std::string& HostConnection::queryGLExtensions(ExtendedRCEncoderContext *rcEnc) {
644     if (!m_glExtensions.empty()) {
645         return m_glExtensions;
646     }
647 
648     // Extensions strings are usually quite long, preallocate enough here.
649     std::string extensions_buffer(1023, '\0');
650 
651     // rcGetGLString() returns required size including the 0-terminator, so
652     // account it when passing/using the sizes.
653     int extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS,
654                                              &extensions_buffer[0],
655                                              extensions_buffer.size() + 1);
656     if (extensionSize < 0) {
657         extensions_buffer.resize(-extensionSize);
658         extensionSize = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS,
659                                              &extensions_buffer[0],
660                                             -extensionSize + 1);
661     }
662 
663     if (extensionSize > 0) {
664         extensions_buffer.resize(extensionSize - 1);
665         m_glExtensions.swap(extensions_buffer);
666     }
667 
668     return m_glExtensions;
669 }
670 
queryAndSetHostCompositionImpl(ExtendedRCEncoderContext * rcEnc)671 void HostConnection::queryAndSetHostCompositionImpl(ExtendedRCEncoderContext *rcEnc) {
672     const std::string& glExtensions = queryGLExtensions(rcEnc);
673     ALOGD("HostComposition ext %s", glExtensions.c_str());
674     // make sure V2 is checked first before V1, as host may declare supporting both
675     if (glExtensions.find(kHostCompositionV2) != std::string::npos) {
676         rcEnc->setHostComposition(HOST_COMPOSITION_V2);
677     }
678     else if (glExtensions.find(kHostCompositionV1) != std::string::npos) {
679         rcEnc->setHostComposition(HOST_COMPOSITION_V1);
680     }
681     else {
682         rcEnc->setHostComposition(HOST_COMPOSITION_NONE);
683     }
684 }
685 
setChecksumHelper(ExtendedRCEncoderContext * rcEnc)686 void HostConnection::setChecksumHelper(ExtendedRCEncoderContext *rcEnc) {
687     const std::string& glExtensions = queryGLExtensions(rcEnc);
688     // check the host supported version
689     uint32_t checksumVersion = 0;
690     const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix();
691     const char* glProtocolStr = strstr(glExtensions.c_str(), checksumPrefix);
692     if (glProtocolStr) {
693         uint32_t maxVersion = ChecksumCalculator::getMaxVersion();
694         sscanf(glProtocolStr+strlen(checksumPrefix), "%d", &checksumVersion);
695         if (maxVersion < checksumVersion) {
696             checksumVersion = maxVersion;
697         }
698         // The ordering of the following two commands matters!
699         // Must tell the host first before setting it in the guest
700         rcEnc->rcSelectChecksumHelper(rcEnc, checksumVersion, 0);
701         m_checksumHelper.setVersion(checksumVersion);
702     }
703 }
704 
queryAndSetSyncImpl(ExtendedRCEncoderContext * rcEnc)705 void HostConnection::queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc) {
706     const std::string& glExtensions = queryGLExtensions(rcEnc);
707 #if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__))
708     rcEnc->setSyncImpl(SYNC_IMPL_NONE);
709 #else
710     if (glExtensions.find(kRCNativeSyncV4) != std::string::npos) {
711         rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V4);
712     } else if (glExtensions.find(kRCNativeSyncV3) != std::string::npos) {
713         rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V3);
714     } else if (glExtensions.find(kRCNativeSyncV2) != std::string::npos) {
715         rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V2);
716     } else {
717         rcEnc->setSyncImpl(SYNC_IMPL_NONE);
718     }
719 #endif
720 }
721 
queryAndSetDmaImpl(ExtendedRCEncoderContext * rcEnc)722 void HostConnection::queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc) {
723     std::string glExtensions = queryGLExtensions(rcEnc);
724 #if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__))
725     rcEnc->setDmaImpl(DMA_IMPL_NONE);
726 #else
727     if (glExtensions.find(kDmaExtStr_v1) != std::string::npos) {
728         rcEnc->setDmaImpl(DMA_IMPL_v1);
729     } else {
730         rcEnc->setDmaImpl(DMA_IMPL_NONE);
731     }
732 #endif
733 }
734 
queryAndSetGLESMaxVersion(ExtendedRCEncoderContext * rcEnc)735 void HostConnection::queryAndSetGLESMaxVersion(ExtendedRCEncoderContext* rcEnc) {
736     std::string glExtensions = queryGLExtensions(rcEnc);
737     if (glExtensions.find(kGLESMaxVersion_2) != std::string::npos) {
738         rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2);
739     } else if (glExtensions.find(kGLESMaxVersion_3_0) != std::string::npos) {
740         rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_0);
741     } else if (glExtensions.find(kGLESMaxVersion_3_1) != std::string::npos) {
742         rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_1);
743     } else if (glExtensions.find(kGLESMaxVersion_3_2) != std::string::npos) {
744         rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_2);
745     } else {
746         ALOGW("Unrecognized GLES max version string in extensions: %s",
747               glExtensions.c_str());
748         rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2);
749     }
750 }
751 
queryAndSetNoErrorState(ExtendedRCEncoderContext * rcEnc)752 void HostConnection::queryAndSetNoErrorState(ExtendedRCEncoderContext* rcEnc) {
753     std::string glExtensions = queryGLExtensions(rcEnc);
754     if (glExtensions.find(kGLESNoHostError) != std::string::npos) {
755         m_noHostError = true;
756     }
757 }
758 
queryAndSetDirectMemSupport(ExtendedRCEncoderContext * rcEnc)759 void HostConnection::queryAndSetDirectMemSupport(ExtendedRCEncoderContext* rcEnc) {
760     std::string glExtensions = queryGLExtensions(rcEnc);
761     if (glExtensions.find(kGLDirectMem) != std::string::npos) {
762         rcEnc->featureInfo()->hasDirectMem = true;
763     }
764 }
765 
queryAndSetVulkanSupport(ExtendedRCEncoderContext * rcEnc)766 void HostConnection::queryAndSetVulkanSupport(ExtendedRCEncoderContext* rcEnc) {
767     std::string glExtensions = queryGLExtensions(rcEnc);
768     if (glExtensions.find(kVulkan) != std::string::npos) {
769         rcEnc->featureInfo()->hasVulkan = true;
770     }
771 }
772 
queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext * rcEnc)773 void HostConnection::queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext* rcEnc) {
774     std::string glExtensions = queryGLExtensions(rcEnc);
775     if (glExtensions.find(kDeferredVulkanCommands) != std::string::npos) {
776         rcEnc->featureInfo()->hasDeferredVulkanCommands = true;
777     }
778 }
779 
queryAndSetVulkanNullOptionalStringsSupport(ExtendedRCEncoderContext * rcEnc)780 void HostConnection::queryAndSetVulkanNullOptionalStringsSupport(ExtendedRCEncoderContext* rcEnc) {
781     std::string glExtensions = queryGLExtensions(rcEnc);
782     if (glExtensions.find(kVulkanNullOptionalStrings) != std::string::npos) {
783         rcEnc->featureInfo()->hasVulkanNullOptionalStrings = true;
784     }
785 }
786 
queryAndSetVulkanCreateResourcesWithRequirementsSupport(ExtendedRCEncoderContext * rcEnc)787 void HostConnection::queryAndSetVulkanCreateResourcesWithRequirementsSupport(ExtendedRCEncoderContext* rcEnc) {
788     std::string glExtensions = queryGLExtensions(rcEnc);
789     if (glExtensions.find(kVulkanCreateResourcesWithRequirements) != std::string::npos) {
790         rcEnc->featureInfo()->hasVulkanCreateResourcesWithRequirements = true;
791     }
792 }
793 
queryAndSetVulkanIgnoredHandles(ExtendedRCEncoderContext * rcEnc)794 void HostConnection::queryAndSetVulkanIgnoredHandles(ExtendedRCEncoderContext* rcEnc) {
795     std::string glExtensions = queryGLExtensions(rcEnc);
796     if (glExtensions.find(kVulkanIgnoredHandles) != std::string::npos) {
797         rcEnc->featureInfo()->hasVulkanIgnoredHandles = true;
798     }
799 }
800 
queryAndSetYUVCache(ExtendedRCEncoderContext * rcEnc)801 void HostConnection::queryAndSetYUVCache(ExtendedRCEncoderContext* rcEnc) {
802     std::string glExtensions = queryGLExtensions(rcEnc);
803     if (glExtensions.find(kYUVCache) != std::string::npos) {
804         rcEnc->featureInfo()->hasYUVCache = true;
805     }
806 }
807 
queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext * rcEnc)808 void HostConnection::queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext* rcEnc) {
809     std::string glExtensions = queryGLExtensions(rcEnc);
810     if (glExtensions.find(kAsyncUnmapBuffer) != std::string::npos) {
811         rcEnc->featureInfo()->hasAsyncUnmapBuffer = true;
812     }
813 }
814 
queryAndSetVirtioGpuNext(ExtendedRCEncoderContext * rcEnc)815 void HostConnection::queryAndSetVirtioGpuNext(ExtendedRCEncoderContext* rcEnc) {
816     std::string glExtensions = queryGLExtensions(rcEnc);
817     if (glExtensions.find(kVirtioGpuNext) != std::string::npos) {
818         rcEnc->featureInfo()->hasVirtioGpuNext = true;
819     }
820 }
821 
queryHasSharedSlotsHostMemoryAllocator(ExtendedRCEncoderContext * rcEnc)822 void HostConnection::queryHasSharedSlotsHostMemoryAllocator(ExtendedRCEncoderContext *rcEnc) {
823     const std::string& glExtensions = queryGLExtensions(rcEnc);
824     if (glExtensions.find(kHasSharedSlotsHostMemoryAllocator) != std::string::npos) {
825         rcEnc->featureInfo()->hasSharedSlotsHostMemoryAllocator = true;
826     }
827 }
828 
queryAndSetVulkanFreeMemorySync(ExtendedRCEncoderContext * rcEnc)829 void HostConnection::queryAndSetVulkanFreeMemorySync(ExtendedRCEncoderContext *rcEnc) {
830     const std::string& glExtensions = queryGLExtensions(rcEnc);
831     if (glExtensions.find(kVulkanFreeMemorySync) != std::string::npos) {
832         rcEnc->featureInfo()->hasVulkanFreeMemorySync = true;
833     }
834 }
835