diff options
| author | Lingfeng Yang <lfy@google.com> | 2020-06-24 20:26:39 +0000 |
|---|---|---|
| committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-06-24 20:26:39 +0000 |
| commit | 056659bab4c70845900467e2b4dd91302a3924ea (patch) | |
| tree | b38e26b5fbdc70374f2de30c75958f6430e9527b | |
| parent | 72b427b973d0544709704c1d69dc9bcd53af8e2d (diff) | |
| parent | 888ccdc609bd75c0d95bb6786109d6215b941c06 (diff) | |
| download | device_generic_goldfish-opengl-056659bab4c70845900467e2b4dd91302a3924ea.tar.gz device_generic_goldfish-opengl-056659bab4c70845900467e2b4dd91302a3924ea.tar.bz2 device_generic_goldfish-opengl-056659bab4c70845900467e2b4dd91302a3924ea.zip | |
Merge "virtio-gpu-asg transport" am: 09f44a32e6 am: 888ccdc609
Original change: https://android-review.googlesource.com/c/device/generic/goldfish-opengl/+/1318758
Change-Id: I399277a8f42dff5957f73fa850dd45682ddc5e71
| -rw-r--r-- | shared/GoldfishAddressSpace/Android.bp | 2 | ||||
| -rw-r--r-- | shared/GoldfishAddressSpace/include/goldfish_address_space.h | 96 | ||||
| -rw-r--r-- | shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl | 257 | ||||
| -rw-r--r-- | shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl | 4 | ||||
| -rw-r--r-- | shared/GoldfishAddressSpace/include/virtio_gpu_next.h | 58 | ||||
| -rw-r--r-- | system/OpenglSystemCommon/AddressSpaceStream.cpp | 157 | ||||
| -rw-r--r-- | system/OpenglSystemCommon/AddressSpaceStream.h | 13 | ||||
| -rw-r--r-- | system/OpenglSystemCommon/EmulatorFeatureInfo.h | 1 | ||||
| -rw-r--r-- | system/OpenglSystemCommon/HostConnection.cpp | 38 | ||||
| -rw-r--r-- | system/OpenglSystemCommon/ProcessPipe.cpp | 3 | ||||
| -rw-r--r-- | system/OpenglSystemCommon/address_space_graphics_types.h | 4 | ||||
| -rw-r--r-- | system/codecs/omx/common/Android.mk | 9 | ||||
| -rw-r--r-- | system/codecs/omx/common/goldfish_media_utils.cpp | 4 | ||||
| -rw-r--r-- | system/hals/Android.mk | 8 |
14 files changed, 628 insertions, 26 deletions
diff --git a/shared/GoldfishAddressSpace/Android.bp b/shared/GoldfishAddressSpace/Android.bp index 6dcdb56a..4e8d31d3 100644 --- a/shared/GoldfishAddressSpace/Android.bp +++ b/shared/GoldfishAddressSpace/Android.bp @@ -6,11 +6,13 @@ cc_library_static { ], shared_libs: [ "liblog", + "libdrm", ], export_include_dirs: [ "include", ], cflags: [ "-DLOG_TAG=\"goldfish-address-space\"", + "-DVIRTIO_GPU", ], } diff --git a/shared/GoldfishAddressSpace/include/goldfish_address_space.h b/shared/GoldfishAddressSpace/include/goldfish_address_space.h index 044e18a8..ad5e3cb9 100644 --- a/shared/GoldfishAddressSpace/include/goldfish_address_space.h +++ b/shared/GoldfishAddressSpace/include/goldfish_address_space.h @@ -49,6 +49,7 @@ enum GoldfishAddressSpaceSubdeviceType { Media = 1, HostMemoryAllocator = 5, SharedSlotsHostMemoryAllocator = 6, + VirtioGpuGraphics = 10, }; class GoldfishAddressSpaceBlockProvider { @@ -135,7 +136,7 @@ private: // require different lifetime expectations versus GoldfishAddressSpaceBlock). // We also expose the ping info struct that is shared between host and guest. -struct goldfish_address_space_ping { +struct address_space_ping { uint64_t offset; uint64_t size; uint64_t metadata; @@ -164,6 +165,97 @@ void* goldfish_address_space_map( void goldfish_address_space_unmap(void* ptr, uint64_t size); bool goldfish_address_space_set_subdevice_type(address_space_handle_t, GoldfishAddressSpaceSubdeviceType type, address_space_handle_t*); -bool goldfish_address_space_ping(address_space_handle_t, struct goldfish_address_space_ping*); +bool goldfish_address_space_ping(address_space_handle_t, struct address_space_ping*); + +// virtio-gpu version + +struct address_space_virtgpu_hostmem_info { + uint32_t id; + uint32_t bo; + void* ptr; +}; + +struct address_space_virtgpu_info { + int fd; + uint32_t resp_bo; + uint32_t resp_resid; + void* resp_mapped_ptr; +}; + +address_space_handle_t virtgpu_address_space_open(); +void virtgpu_address_space_close(address_space_handle_t); + +// Ping with no response +bool virtgpu_address_space_ping(address_space_handle_t, struct address_space_ping*); + +bool virtgpu_address_space_create_context_with_subdevice( + address_space_handle_t, + uint32_t subdevice_type, + struct address_space_virtgpu_info* info_out); + +bool virtgpu_address_space_allocate_hostmem( + address_space_handle_t fd, + size_t size, + uint64_t hostmem_id, + struct address_space_virtgpu_hostmem_info* hostmem_info_out); + +// Ping with response +bool virtgpu_address_space_ping_with_response( + struct address_space_virtgpu_info* info, + struct address_space_ping* ping); + +// typedef/struct to abstract over goldfish vs virtio-gpu implementations +typedef address_space_handle_t (*address_space_open_t)(void); +typedef void (*address_space_close_t)(address_space_handle_t); + +typedef bool (*address_space_allocate_t)( + address_space_handle_t, size_t size, uint64_t* phys_addr, uint64_t* offset); +typedef bool (*address_space_free_t)( + address_space_handle_t, uint64_t offset); + +typedef bool (*address_space_claim_shared_t)( + address_space_handle_t, uint64_t offset, uint64_t size); +typedef bool (*address_space_unclaim_shared_t)( + address_space_handle_t, uint64_t offset); + +// pgoff is the offset into the page to return in the result +typedef void* (*address_space_map_t)( + address_space_handle_t, uint64_t offset, uint64_t size, uint64_t pgoff); +typedef void (*address_space_unmap_t)(void* ptr, uint64_t size); + +typedef bool (*address_space_set_subdevice_type_t)( + address_space_handle_t, GoldfishAddressSpaceSubdeviceType type, address_space_handle_t*); +typedef bool (*address_space_ping_t)( + address_space_handle_t, struct address_space_ping*); + +// Specific to virtio-gpu +typedef bool (*address_space_create_context_with_subdevice_t)( + address_space_handle_t, + uint32_t subdevice_type, + struct address_space_virtgpu_info* info_out); + +typedef bool (*address_space_allocate_hostmem_t)( + address_space_handle_t fd, + size_t size, + uint64_t hostmem_id, + struct address_space_virtgpu_hostmem_info* hostmem_info_out); + +typedef bool (*address_space_ping_with_response_t)( + struct address_space_virtgpu_info* info, + struct address_space_ping* ping); + +struct address_space_ops { + address_space_open_t open; + address_space_close_t close; + address_space_claim_shared_t claim_shared; + address_space_unclaim_shared_t unclaim_shared; + address_space_map_t map; + address_space_unmap_t unmap; + address_space_set_subdevice_type_t set_subdevice_type; + address_space_ping_t ping; + address_space_create_context_with_subdevice_t create_context_with_subdevice; + address_space_allocate_hostmem_t allocate_hostmem; + address_space_ping_with_response_t ping_with_response; +}; #endif // #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_ADDRESS_SPACE_H diff --git a/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl index 8ff7e786..a8a70af3 100644 --- a/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl +++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl @@ -25,9 +25,15 @@ #include <errno.h> #include <memory> +#ifdef VIRTIO_GPU +#include <drm/virtgpu_drm.h> +#include <xf86drm.h> +#endif + #include <log/log.h> #include "goldfish_address_space.h" +#include "virtio_gpu_next.h" namespace { @@ -46,7 +52,7 @@ struct goldfish_address_space_claim_shared { #define GOLDFISH_ADDRESS_SPACE_IOCTL_OP(OP, T) _IOWR(GOLDFISH_ADDRESS_SPACE_IOCTL_MAGIC, OP, T) #define GOLDFISH_ADDRESS_SPACE_IOCTL_ALLOCATE_BLOCK GOLDFISH_ADDRESS_SPACE_IOCTL_OP(10, struct goldfish_address_space_allocate_block) #define GOLDFISH_ADDRESS_SPACE_IOCTL_DEALLOCATE_BLOCK GOLDFISH_ADDRESS_SPACE_IOCTL_OP(11, __u64) -#define GOLDFISH_ADDRESS_SPACE_IOCTL_PING GOLDFISH_ADDRESS_SPACE_IOCTL_OP(12, struct goldfish_address_space_ping) +#define GOLDFISH_ADDRESS_SPACE_IOCTL_PING GOLDFISH_ADDRESS_SPACE_IOCTL_OP(12, struct address_space_ping) #define GOLDFISH_ADDRESS_SPACE_IOCTL_CLAIM_SHARED GOLDFISH_ADDRESS_SPACE_IOCTL_OP(13, struct goldfish_address_space_claim_shared) #define GOLDFISH_ADDRESS_SPACE_IOCTL_UNCLAIM_SHARED GOLDFISH_ADDRESS_SPACE_IOCTL_OP(14, __u64) @@ -70,14 +76,14 @@ long ioctl_deallocate(int fd, uint64_t offset) return ::ioctl(fd, GOLDFISH_ADDRESS_SPACE_IOCTL_DEALLOCATE_BLOCK, &offset); } -long ioctl_ping(int fd, struct goldfish_address_space_ping *request) +long ioctl_ping(int fd, struct address_space_ping *request) { return ::ioctl(fd, GOLDFISH_ADDRESS_SPACE_IOCTL_PING, request); } long set_address_space_subdevice_type(int fd, uint64_t type) { - struct goldfish_address_space_ping request; + struct address_space_ping request; ::memset(&request, 0, sizeof(request)); request.version = sizeof(request); request.metadata = type; @@ -359,7 +365,7 @@ long GoldfishAddressSpaceHostMemoryAllocator::hostMalloc(GoldfishAddressSpaceBlo return -ENODEV; } - struct goldfish_address_space_ping request; + struct address_space_ping request; if (m_useSharedSlots) { // shared memory slots are supported ::memset(&request, 0, sizeof(request)); @@ -415,7 +421,7 @@ void GoldfishAddressSpaceHostMemoryAllocator::hostFree(GoldfishAddressSpaceBlock } if (block->guestPtr()) { - struct goldfish_address_space_ping request; + struct address_space_ping request; ::memset(&request, 0, sizeof(request)); request.version = sizeof(request); request.offset = block->offset(); @@ -517,7 +523,7 @@ void goldfish_address_space_unmap(void* ptr, uint64_t size) { bool goldfish_address_space_set_subdevice_type( address_space_handle_t handle, GoldfishAddressSpaceSubdeviceType type, address_space_handle_t* handle_out) { - struct goldfish_address_space_ping request; + struct address_space_ping request; request.metadata = (uint64_t)type; *handle_out = handle; return goldfish_address_space_ping(handle, &request); @@ -525,7 +531,7 @@ bool goldfish_address_space_set_subdevice_type( bool goldfish_address_space_ping( address_space_handle_t handle, - struct goldfish_address_space_ping* ping) { + struct address_space_ping* ping) { long res = ioctl_ping(handle, ping); if (res) { @@ -535,3 +541,240 @@ bool goldfish_address_space_ping( return true; } + +// virtio-gpu version +address_space_handle_t virtgpu_address_space_open() { +return drmOpenRender(128); +} + +void virtgpu_address_space_close(address_space_handle_t fd) { +close(fd); +} + +// kVirtioGpuAddressSpaceContextCreateWithSubdevice | subdeviceType +const uint32_t kVirtioGpuAddressSpaceContextCreateWithSubdevice = 0x1001; + +// kVirtioGpuAddressSpacePing | offset_lo | offset_hi | size_lo | size_hi | metadata_lo | metadata_hi | version | wait_fd | wait_flags | direction +// no output +const uint32_t kVirtioGpuAddressSpacePing = 0x1002; + +// kVirtioGpuAddressSpacePingWithResponse | resp_resid | offset_lo | offset_hi | metadata_lo | metadata_hi | version | wait_fd | wait_flags | direction +// out: same as input then | out: error +const uint32_t kVirtioGpuAddressSpacePingWithResponse = 0x1003; + +// Ping with no response +bool virtgpu_address_space_ping(address_space_handle_t fd, struct address_space_ping* info) { + + uint32_t words[] = { + kVirtioGpuAddressSpacePing, + (uint32_t)(info->offset), (uint32_t)(info->offset >> 32), + (uint32_t)(info->size), (uint32_t)(info->size >> 32), + (uint32_t)(info->metadata), (uint32_t)(info->metadata >> 32), + (uint32_t)(info->version), (uint32_t)(info->wait_fd), + (uint32_t)(info->wait_flags), (uint32_t)(info->direction), + }; + + drm_virtgpu_execbuffer execbuffer = { + .flags = 0, + .size = sizeof(words), + .command = (uint64_t)(uintptr_t)(words), + .bo_handles = 0, + .num_bo_handles = 0, + .fence_fd = -1, + }; + + int queue_work_err = drmIoctl(fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &execbuffer); + + if (queue_work_err) { + ALOGE("%s: failed with %d executing command buffer (%s)\n", __func__, + queue_work_err, strerror(errno)); + return false; + } + + return true; +} + +bool virtgpu_address_space_create_context_with_subdevice( + address_space_handle_t fd, + uint32_t subdevice_type, + struct address_space_virtgpu_info* info_out) { + + // response page + drm_virtgpu_resource_create create = { + .target = PIPE_BUFFER, + .format = VIRGL_FORMAT_R8_UNORM, + .bind = VIRGL_BIND_CUSTOM, + .width = 4096, + .height = 1U, + .depth = 1U, + .array_size = 0U, + .size = 4096, + .stride = 4096, + }; + + int ret = drmIoctl(fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &create); + if (ret) { + ALOGE("%s: failed with %d allocating command buffer (%s)\n", + __func__, ret, strerror(errno)); + return false; + } + + drm_virtgpu_map map = { + .handle = create.bo_handle, + }; + + ret = drmIoctl(fd, DRM_IOCTL_VIRTGPU_MAP, &map); + if (ret) { + ALOGE("%s: failed with %d mapping command response buffer (%s)\n", + __func__, ret, strerror(errno)); + return false; + } + + void* ptr = static_cast<unsigned char*>( + mmap64(nullptr, 4096, PROT_WRITE, MAP_SHARED, fd, map.offset)); + + if (ptr == MAP_FAILED) { + ALOGE("%s: failed with %d mmap'ing command response buffer (%s)\n", + __func__, errno, strerror(errno)); + return false; + } + + info_out->fd = fd; + info_out->resp_bo = create.bo_handle; + info_out->resp_resid = create.res_handle; + info_out->resp_mapped_ptr = ptr; + + ALOGD("%s: resp bo: %u resid %u mapped %p\n", __func__, + create.bo_handle, create.res_handle, ptr); + + // Context creation command + uint32_t words[] = { + kVirtioGpuAddressSpaceContextCreateWithSubdevice, + subdevice_type, + }; + + drm_virtgpu_execbuffer execbuffer = { + .flags = 0, + .size = sizeof(words), + .command = (uint64_t)(uintptr_t)(words), + .bo_handles = 0, + .num_bo_handles = 0, + .fence_fd = -1, + }; + + int queue_work_err = drmIoctl(fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &execbuffer); + + if (queue_work_err) { + ALOGE("%s: failed with %d executing command buffer (%s)\n", __func__, + queue_work_err, strerror(errno)); + return false; + } + + return true; +} + +bool virtgpu_address_space_allocate_hostmem( + address_space_handle_t fd, + size_t size, + uint64_t hostmem_id, + struct address_space_virtgpu_hostmem_info* hostmem_info_out) { + + struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 }; + drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST; + drm_rc_blob.blob_flags = VIRTGPU_BLOB_FLAG_MAPPABLE; + drm_rc_blob.blob_id = hostmem_id; + drm_rc_blob.size = size; + + int res = drmIoctl( + fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob); + + if (res) { + ALOGE("%s: Failed to resource create v2: sterror: %s errno: %d\n", __func__, + strerror(errno), errno); + abort(); + } + + struct drm_virtgpu_map map_info = { + .handle = drm_rc_blob.bo_handle, + }; + + res = drmIoctl(fd, DRM_IOCTL_VIRTGPU_MAP, &map_info); + if (res) { + ALOGE("%s: Failed to virtgpu map: sterror: %s errno: %d\n", __func__, + strerror(errno), errno); + abort(); + } + + void* directMappedAddr = mmap64(0, size, PROT_WRITE, MAP_SHARED, fd, map_info.offset); + + if (!directMappedAddr) { + ALOGE("%s: mmap of virtio gpu resource failed\n", __func__); + abort(); + } + + hostmem_info_out->id = hostmem_id; + hostmem_info_out->bo = drm_rc_blob.bo_handle; + hostmem_info_out->ptr = directMappedAddr; + return true; +} + +uint64_t buildu64(uint32_t lo, uint32_t hi) { + uint64_t res = (uint64_t)lo; + uint64_t hi64 = (uint64_t)hi; + return res | (hi64 << 32); +} + +// Ping with response +bool virtgpu_address_space_ping_with_response( + struct address_space_virtgpu_info* info, + struct address_space_ping* ping) { + + uint32_t words[] = { + kVirtioGpuAddressSpacePingWithResponse, + info->resp_resid, + (uint32_t)(ping->offset), (uint32_t)(ping->offset >> 32), + (uint32_t)(ping->size), (uint32_t)(ping->size >> 32), + (uint32_t)(ping->metadata), (uint32_t)(ping->metadata >> 32), + (uint32_t)(ping->version), (uint32_t)(ping->wait_fd), + (uint32_t)(ping->wait_flags), (uint32_t)(ping->direction), + }; + + drm_virtgpu_execbuffer execbuffer = { + .flags = 0, + .size = sizeof(words), + .command = (uint64_t)(uintptr_t)(words), + .bo_handles = (uint64_t)(uintptr_t)(&info->resp_bo), + .num_bo_handles = 1, + .fence_fd = -1, + }; + + int queue_work_err = drmIoctl(info->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &execbuffer); + + if (queue_work_err) { + ALOGE("%s: failed with %d executing command buffer (%s)\n", __func__, + queue_work_err, strerror(errno)); + return false; + } + + struct drm_virtgpu_3d_wait waitcmd; + memset(&waitcmd, 0, sizeof(waitcmd)); + waitcmd.handle = info->resp_bo; + + int ret = drmIoctl(info->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd); + if (ret) { + ALOGE("%s: DRM_IOCTL_VIRTGPU_WAIT failed with %d (%s)\n", __func__, errno, strerror(errno)); + return false; + } + + uint32_t* respWords = (uint32_t*)info->resp_mapped_ptr; + + ping->offset = buildu64(respWords[0], respWords[1]); + ping->size = buildu64(respWords[2], respWords[3]); + ping->metadata = buildu64(respWords[4], respWords[5]); + ping->version = respWords[6]; + ping->wait_fd = respWords[7]; + ping->wait_flags = respWords[8]; + ping->direction = respWords[9]; + + return true; +} diff --git a/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl index 8995c6bb..d1fa4a34 100644 --- a/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl +++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl @@ -377,7 +377,7 @@ void goldfish_address_space_unmap(void*, uint64_t) { } bool goldfish_address_space_set_subdevice_type( address_space_handle_t handle, GoldfishAddressSpaceSubdeviceType type, address_space_handle_t* handle_out) { - struct goldfish_address_space_ping request; + struct address_space_ping request; request.metadata = (uint64_t)type; *handle_out = handle; return goldfish_address_space_ping(handle, &request); @@ -385,7 +385,7 @@ bool goldfish_address_space_set_subdevice_type( bool goldfish_address_space_ping( address_space_handle_t handle, - struct goldfish_address_space_ping* ping) { + struct address_space_ping* ping) { AddressSpaceDevicePingInfo* asHostPingInfo = reinterpret_cast<AddressSpaceDevicePingInfo*>(ping); diff --git a/shared/GoldfishAddressSpace/include/virtio_gpu_next.h b/shared/GoldfishAddressSpace/include/virtio_gpu_next.h new file mode 100644 index 00000000..610dc517 --- /dev/null +++ b/shared/GoldfishAddressSpace/include/virtio_gpu_next.h @@ -0,0 +1,58 @@ +// Copyright (C) 2020 The Android Open Source Project +// Copyright (C) 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifndef HOST_BUILD +#include "drm.h" +#endif + +#define PIPE_BUFFER 0 +#define VIRGL_FORMAT_R8_UNORM 64 +#define VIRGL_BIND_CUSTOM (1 << 17) + +#define DRM_VIRTGPU_RESOURCE_CREATE_BLOB 0x0a + +#define VIRTGPU_PARAM_RESOURCE_BLOB 3 /* DRM_VIRTGPU_RESOURCE_CREATE_BLOB */ +#define VIRTGPU_PARAM_HOST_VISIBLE 4 + +struct drm_virtgpu_resource_create_blob { +#define VIRTGPU_BLOB_MEM_GUEST 0x0001 +#define VIRTGPU_BLOB_MEM_HOST 0x0002 +#define VIRTGPU_BLOB_MEM_HOST_GUEST 0x0003 + +#define VIRTGPU_BLOB_FLAG_MAPPABLE 0x0001 +#define VIRTGPU_BLOB_FLAG_SHAREABLE 0x0002 +#define VIRTGPU_BLOB_FLAG_CROSS_DEVICE 0x0004 + /* zero is invalid blob_mem */ + uint32_t blob_mem; + uint32_t blob_flags; + uint32_t bo_handle; + uint32_t res_handle; + uint64_t size; + + /* + * for 3D contexts with VIRTGPU_BLOB_MEM_HOSTGUEST and + * VIRTGPU_BLOB_MEM_HOST otherwise, must be zero. + */ + uint32_t pad; + uint32_t cmd_size; + uint64_t cmd; + uint64_t blob_id; +}; + + +#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE_BLOB, \ + struct drm_virtgpu_resource_create_blob) diff --git a/system/OpenglSystemCommon/AddressSpaceStream.cpp b/system/OpenglSystemCommon/AddressSpaceStream.cpp index 7c0f1546..bb94433e 100644 --- a/system/OpenglSystemCommon/AddressSpaceStream.cpp +++ b/system/OpenglSystemCommon/AddressSpaceStream.cpp @@ -42,7 +42,7 @@ AddressSpaceStream* createAddressSpaceStream(size_t ignored_bufSize) { return nullptr; } - struct goldfish_address_space_ping request; + struct address_space_ping request; request.metadata = ASG_GET_RING; if (!goldfish_address_space_ping(child_device_handle, &request)) { ALOGE("AddressSpaceStream::create failed (get ring)\n"); @@ -123,21 +123,156 @@ AddressSpaceStream* createAddressSpaceStream(size_t ignored_bufSize) { context.ring_config->host_consumed_pos = 0; context.ring_config->guest_write_pos = 0; + struct address_space_ops ops = { + .open = goldfish_address_space_open, + .close = goldfish_address_space_close, + .claim_shared = goldfish_address_space_claim_shared, + .unclaim_shared = goldfish_address_space_unclaim_shared, + .map = goldfish_address_space_map, + .unmap = goldfish_address_space_unmap, + .set_subdevice_type = goldfish_address_space_set_subdevice_type, + .ping = goldfish_address_space_ping, + }; + AddressSpaceStream* res = new AddressSpaceStream( child_device_handle, version, context, - ringOffset, bufferOffset); + ringOffset, bufferOffset, false /* not virtio */, ops); return res; } +#ifdef HOST_BUILD +AddressSpaceStream* createVirtioGpuAddressSpaceStream(size_t ignored_bufSize) { + // Ignore incoming ignored_bufSize + (void)ignored_bufSize; + return nullptr; +} +#else +AddressSpaceStream* createVirtioGpuAddressSpaceStream(size_t ignored_bufSize) { + // Ignore incoming ignored_bufSize + (void)ignored_bufSize; + + auto handle = virtgpu_address_space_open(); + + if (handle <= 0) { + ALOGE("AddressSpaceStream::create failed (open device)\n"); + return nullptr; + } + + struct address_space_virtgpu_info virtgpu_info; + + ALOGD("%s: create subdevice and get resp\n", __func__); + if (!virtgpu_address_space_create_context_with_subdevice( + handle, GoldfishAddressSpaceSubdeviceType::VirtioGpuGraphics, + &virtgpu_info)) { + ALOGE("AddressSpaceStream::create failed (create subdevice)\n"); + virtgpu_address_space_close(handle); + return nullptr; + } + ALOGD("%s: create subdevice and get resp (done)\n", __func__); + + struct address_space_ping request; + uint32_t ringSize = 0; + uint32_t bufferSize = 0; + + request.metadata = ASG_GET_RING; + if (!virtgpu_address_space_ping_with_response( + &virtgpu_info, &request)) { + ALOGE("AddressSpaceStream::create failed (get ring version)\n"); + virtgpu_address_space_close(handle); + return nullptr; + } + ringSize = request.size; + + request.metadata = ASG_GET_BUFFER; + if (!virtgpu_address_space_ping_with_response( + &virtgpu_info, &request)) { + ALOGE("AddressSpaceStream::create failed (get ring version)\n"); + virtgpu_address_space_close(handle); + return nullptr; + } + bufferSize = request.size; + + request.metadata = ASG_SET_VERSION; + request.size = 1; // version 1 + + if (!virtgpu_address_space_ping_with_response( + &virtgpu_info, &request)) { + ALOGE("AddressSpaceStream::create failed (set version)\n"); + virtgpu_address_space_close(handle); + return nullptr; + } + + ALOGD("%s: ping returned. context ring and buffer sizes %u %u\n", __func__, + ringSize, bufferSize); + + uint64_t hostmem_id = request.metadata; + uint32_t version = request.size; + size_t hostmem_alloc_size = + (size_t)(ringSize + bufferSize); + + ALOGD("%s: hostmem size: %zu\n", __func__, hostmem_alloc_size); + + struct address_space_virtgpu_hostmem_info hostmem_info; + if (!virtgpu_address_space_allocate_hostmem( + handle, + hostmem_alloc_size, + hostmem_id, + &hostmem_info)) { + ALOGE("AddressSpaceStream::create failed (alloc hostmem)\n"); + virtgpu_address_space_close(handle); + return nullptr; + } + + request.metadata = ASG_GET_CONFIG; + if (!virtgpu_address_space_ping_with_response( + &virtgpu_info, &request)) { + ALOGE("AddressSpaceStream::create failed (get config)\n"); + virtgpu_address_space_close(handle); + return nullptr; + } + + char* ringPtr = (char*)hostmem_info.ptr; + char* bufferPtr = ((char*)hostmem_info.ptr) + sizeof(struct asg_ring_storage); + + struct asg_context context = + asg_context_create( + (char*)ringPtr, (char*)bufferPtr, bufferSize); + + context.ring_config->transfer_mode = 1; + context.ring_config->host_consumed_pos = 0; + context.ring_config->guest_write_pos = 0; + + struct address_space_ops ops = { + .open = virtgpu_address_space_open, + .close = virtgpu_address_space_close, + .ping = virtgpu_address_space_ping, + .allocate_hostmem = virtgpu_address_space_allocate_hostmem, + .ping_with_response = virtgpu_address_space_ping_with_response, + }; + + AddressSpaceStream* res = + new AddressSpaceStream( + handle, version, context, + 0, 0, true /* is virtio */, ops); + + return res; +} +#endif + + AddressSpaceStream::AddressSpaceStream( address_space_handle_t handle, uint32_t version, struct asg_context context, uint64_t ringOffset, - uint64_t writeBufferOffset) : + uint64_t writeBufferOffset, + bool virtioMode, + struct address_space_ops ops) : IOStream(context.ring_config->flush_interval), + m_virtioMode(virtioMode), + m_ops(ops), m_tmpBuf(0), m_tmpBufSize(0), m_tmpBufXferSize(0), @@ -163,11 +298,13 @@ AddressSpaceStream::AddressSpaceStream( } AddressSpaceStream::~AddressSpaceStream() { - goldfish_address_space_unmap(m_context.to_host, sizeof(struct asg_ring_storage)); - goldfish_address_space_unmap(m_context.buffer, m_writeBufferSize); - goldfish_address_space_unclaim_shared(m_handle, m_ringOffset); - goldfish_address_space_unclaim_shared(m_handle, m_writeBufferOffset); - goldfish_address_space_close(m_handle); + if (!m_virtioMode) { + m_ops.unmap(m_context.to_host, sizeof(struct asg_ring_storage)); + m_ops.unmap(m_context.buffer, m_writeBufferSize); + m_ops.unclaim_shared(m_handle, m_ringOffset); + m_ops.unclaim_shared(m_handle, m_writeBufferOffset); + } + m_ops.close(m_handle); if (m_readBuf) free(m_readBuf); if (m_tmpBuf) free(m_tmpBuf); } @@ -433,9 +570,9 @@ ssize_t AddressSpaceStream::speculativeRead(unsigned char* readBuffer, size_t tr } void AddressSpaceStream::notifyAvailable() { - struct goldfish_address_space_ping request; + struct address_space_ping request; request.metadata = ASG_NOTIFY_AVAILABLE; - goldfish_address_space_ping(m_handle, &request); + m_ops.ping(m_handle, &request); ++m_notifs; } diff --git a/system/OpenglSystemCommon/AddressSpaceStream.h b/system/OpenglSystemCommon/AddressSpaceStream.h index a4db5aa1..3d60695e 100644 --- a/system/OpenglSystemCommon/AddressSpaceStream.h +++ b/system/OpenglSystemCommon/AddressSpaceStream.h @@ -24,6 +24,7 @@ class AddressSpaceStream; AddressSpaceStream* createAddressSpaceStream(size_t bufSize); +AddressSpaceStream* createVirtioGpuAddressSpaceStream(size_t bufSize); class AddressSpaceStream : public IOStream { public: @@ -32,7 +33,9 @@ public: uint32_t version, struct asg_context context, uint64_t ringOffset, - uint64_t writeBufferOffset); + uint64_t writeBufferOffset, + bool virtioMode, + struct address_space_ops ops); ~AddressSpaceStream(); virtual size_t idealAllocSize(size_t len); @@ -43,6 +46,11 @@ public: virtual int writeFully(const void *buf, size_t len); virtual const unsigned char *commitBufferAndReadFully(size_t size, void *buf, size_t len); + int getRendernodeFd() const { + if (!m_virtioMode) return -1; + return m_handle; + } + private: bool isInError() const; ssize_t speculativeRead(unsigned char* readBuffer, size_t trySize); @@ -54,6 +62,9 @@ private: void ensureType3Finished(); int type1Write(uint32_t offset, size_t size); + bool m_virtioMode; + struct address_space_ops m_ops; + unsigned char* m_tmpBuf; size_t m_tmpBufSize; size_t m_tmpBufXferSize; diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h index f1505fea..7545e5a1 100644 --- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h +++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h @@ -154,6 +154,7 @@ enum HostConnectionType { HOST_CONNECTION_VIRTIO_GPU = 2, HOST_CONNECTION_ADDRESS_SPACE = 3, HOST_CONNECTION_VIRTIO_GPU_PIPE = 4, + HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE = 5, }; enum GrallocType { diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp index 72ea1f0c..8ab05eaa 100644 --- a/system/OpenglSystemCommon/HostConnection.cpp +++ b/system/OpenglSystemCommon/HostConnection.cpp @@ -58,6 +58,10 @@ AddressSpaceStream* createAddressSpaceStream(size_t bufSize) { ALOGE("%s: FATAL: Trying to create ASG stream in unsupported build\n", __func__); abort(); } +AddressSpaceStream* createVirtioGpuAddressSpaceStream(size_t bufSize) { + ALOGE("%s: FATAL: Trying to create virtgpu ASG stream in unsupported build\n", __func__); + abort(); +} #endif using goldfish_vk::VkEncoder; @@ -112,6 +116,7 @@ static HostConnectionType getConnectionTypeFromProperty() { if (!strcmp("virtio-gpu", transportValue)) return HOST_CONNECTION_VIRTIO_GPU; if (!strcmp("asg", transportValue)) return HOST_CONNECTION_ADDRESS_SPACE; if (!strcmp("virtio-gpu-pipe", transportValue)) return HOST_CONNECTION_VIRTIO_GPU_PIPE; + if (!strcmp("virtio-gpu-asg", transportValue)) return HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE; return HOST_CONNECTION_QEMU_PIPE; #endif @@ -491,7 +496,37 @@ HostConnection* HostConnection::connect(HostConnection* con) { con->m_grallocType = getGrallocTypeFromProperty(); con->m_stream = stream; con->m_rendernodeFdOwned = false; - con->m_rendernodeFdOwned = stream->getRendernodeFd(); + con->m_rendernodeFd = stream->getRendernodeFd(); + switch (con->m_grallocType) { + case GRALLOC_TYPE_RANCHU: + con->m_grallocHelper = &m_goldfishGralloc; + break; + case GRALLOC_TYPE_MINIGBM: { + MinigbmGralloc* m = new MinigbmGralloc; + m->setFd(stream->getRendernodeFd()); + con->m_grallocHelper = m; + break; + } + default: + ALOGE("Fatal: Unknown gralloc type 0x%x\n", con->m_grallocType); + abort(); + } + con->m_processPipe = &m_goldfishProcessPipe; + break; + } +#ifndef HOST_BUILD + case HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE: { + AddressSpaceStream *stream = createVirtioGpuAddressSpaceStream(STREAM_BUFFER_SIZE); + if (!stream) { + ALOGE("Failed to create virtgpu AddressSpaceStream for host connection!!!\n"); + delete con; + return NULL; + } + con->m_connectionType = HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE; + con->m_grallocType = getGrallocTypeFromProperty(); + con->m_stream = stream; + con->m_rendernodeFdOwned = false; + con->m_rendernodeFd = stream->getRendernodeFd(); switch (con->m_grallocType) { case GRALLOC_TYPE_RANCHU: con->m_grallocHelper = &m_goldfishGralloc; @@ -509,6 +544,7 @@ HostConnection* HostConnection::connect(HostConnection* con) { con->m_processPipe = &m_goldfishProcessPipe; break; } +#endif // !HOST_BUILD #else default: break; diff --git a/system/OpenglSystemCommon/ProcessPipe.cpp b/system/OpenglSystemCommon/ProcessPipe.cpp index 84764f4e..0d747890 100644 --- a/system/OpenglSystemCommon/ProcessPipe.cpp +++ b/system/OpenglSystemCommon/ProcessPipe.cpp @@ -166,7 +166,8 @@ static void processPipeInitOnce() { case HOST_CONNECTION_VIRTIO_GPU: sQemuPipeInit(); break; - case HOST_CONNECTION_VIRTIO_GPU_PIPE: { + case HOST_CONNECTION_VIRTIO_GPU_PIPE: + case HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE: { sVirtioGpuPipeStream = new VirtioGpuPipeStream(4096); sProcUID = sVirtioGpuPipeStream->initProcessPipe(); break; diff --git a/system/OpenglSystemCommon/address_space_graphics_types.h b/system/OpenglSystemCommon/address_space_graphics_types.h index 1ebad348..5f0e9b67 100644 --- a/system/OpenglSystemCommon/address_space_graphics_types.h +++ b/system/OpenglSystemCommon/address_space_graphics_types.h @@ -342,6 +342,7 @@ enum asg_command { // version and can proceed with a protocol that works for both. // size (in): the version of the guest // size (out): the version of the host + // metadata (out): hostmem id // After this command runs, the consumer is // implicitly created. ASG_SET_VERSION = 2, @@ -349,6 +350,9 @@ enum asg_command { // Ping(notiy_available): Wakes up the consumer from sleep so it // can read data via toHost ASG_NOTIFY_AVAILABLE = 3, + + // Retrieve the host config + ASG_GET_CONFIG = 4, }; } // extern "C" diff --git a/system/codecs/omx/common/Android.mk b/system/codecs/omx/common/Android.mk index 9e233e79..4daf0b73 100644 --- a/system/codecs/omx/common/Android.mk +++ b/system/codecs/omx/common/Android.mk @@ -33,6 +33,15 @@ ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST)) $(call emugl-import,libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX)) else $(call emugl-export,STATIC_LIBRARIES,libGoldfishAddressSpace) + +ifeq (true,$(BUILD_EMULATOR_VULKAN)) + +LOCAL_CFLAGS += -DVIRTIO_GPU +LOCAL_C_INCLUDES += external/libdrm external/minigbm/cros_gralloc +LOCAL_SHARED_LIBRARIES += libdrm + +endif + endif $(call emugl-end-module) diff --git a/system/codecs/omx/common/goldfish_media_utils.cpp b/system/codecs/omx/common/goldfish_media_utils.cpp index a2057ab4..4f4ead0f 100644 --- a/system/codecs/omx/common/goldfish_media_utils.cpp +++ b/system/codecs/omx/common/goldfish_media_utils.cpp @@ -123,7 +123,7 @@ GoldfishMediaTransportImpl::GoldfishMediaTransportImpl() { mStartPtr = goldfish_address_space_map(mHandle, mOffset, mSize); ALOGI("guest address is %p", mStartPtr); - struct goldfish_address_space_ping pingInfo; + struct address_space_ping pingInfo; pingInfo.metadata = GoldfishAddressSpaceSubdeviceType::Media; pingInfo.offset = mOffset; if (goldfish_address_space_ping(mHandle, &pingInfo) == false) { @@ -185,7 +185,7 @@ void GoldfishMediaTransportImpl::writeParam(__u64 val, unsigned int num, unsigne bool GoldfishMediaTransportImpl::sendOperation(MediaCodecType type, MediaOperation op, unsigned int offSetToStartAddr) { - struct goldfish_address_space_ping pingInfo; + struct address_space_ping pingInfo; pingInfo.metadata = makeMetadata(type, op, offSetToStartAddr); pingInfo.offset = mOffset; // + (offSetToStartAddr); if (goldfish_address_space_ping(mHandle, &pingInfo) == false) { diff --git a/system/hals/Android.mk b/system/hals/Android.mk index 3cdb4bfa..1641d237 100644 --- a/system/hals/Android.mk +++ b/system/hals/Android.mk @@ -45,6 +45,10 @@ LOCAL_C_INCLUDES += \ device/generic/goldfish-opengl/host/include/libOpenglRender \ device/generic/goldfish-opengl/system/renderControl_enc \ +LOCAL_CFLAGS += -DVIRTIO_GPU +LOCAL_C_INCLUDES += external/libdrm external/minigbm/cros_gralloc +LOCAL_SHARED_LIBRARIES += libdrm + include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) @@ -78,5 +82,9 @@ LOCAL_C_INCLUDES += \ device/generic/goldfish-opengl/host/include/libOpenglRender \ device/generic/goldfish-opengl/system/renderControl_enc \ +LOCAL_CFLAGS += -DVIRTIO_GPU +LOCAL_C_INCLUDES += external/libdrm external/minigbm/cros_gralloc +LOCAL_SHARED_LIBRARIES += libdrm + include $(BUILD_SHARED_LIBRARY) |
