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