1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <stdint.h>
18 
19 #include <memory>
20 #include <optional>
21 #include <unordered_set>
22 
23 extern "C" {
24 #include "host-common/goldfish_pipe.h"
25 }  // extern "C"
26 
27 #include "ExternalObjectManager.h"
28 #include "VirtioGpu.h"
29 #ifdef GFXSTREAM_BUILD_WITH_SNAPSHOT_FRONTEND_SUPPORT
30 #include "VirtioGpuResourceSnapshot.pb.h"
31 #endif  // GFXSTREAM_BUILD_WITH_SNAPSHOT_FRONTEND_SUPPORT
32 #include "VirtioGpuRingBlob.h"
33 #include "gfxstream/host/Features.h"
34 #include "gfxstream/virtio-gpu-gfxstream-renderer-unstable.h"
35 #include "gfxstream/virtio-gpu-gfxstream-renderer.h"
36 
37 namespace gfxstream {
38 namespace host {
39 
40 // LINT.IfChange(virtio_gpu_resource_type)
41 enum class VirtioGpuResourceType {
42     UNKNOWN = 0,
43     // Used as a communication channel between the guest and the host
44     // which does not need an allocation on the host GPU.
45     PIPE = 1,
46     // Used as a GPU data buffer.
47     BUFFER = 2,
48     // Used as a GPU texture.
49     COLOR_BUFFER = 3,
50     // Used as a blob and not known to FrameBuffer.
51     BLOB = 4,
52 };
53 // LINT.ThenChange(VirtioGpuResourceSnapshot.proto:virtio_gpu_resource_type)
54 
55 class VirtioGpuResource {
56    public:
VirtioGpuResource()57     VirtioGpuResource() {}
58 
59     static std::optional<VirtioGpuResource> Create(
60         const struct stream_renderer_resource_create_args* args, struct iovec* iov,
61         uint32_t num_iovs);
62 
63     static std::optional<VirtioGpuResource> Create(
64         const gfxstream::host::FeatureSet& features, uint32_t pageSize, uint32_t contextId,
65         uint32_t resourceId, const struct stream_renderer_resource_create_args* createArgs,
66         const struct stream_renderer_create_blob* createBlobArgs,
67         const struct stream_renderer_handle* handle);
68 
69     int Destroy();
70 
GetId()71     VirtioGpuResourceId GetId() const { return mId; }
72 
73     void AttachIov(struct iovec* iov, uint32_t num_iovs);
74     void DetachIov();
75 
76     void AttachToContext(VirtioGpuContextId contextId);
77     void DetachFromContext(VirtioGpuContextId contextId);
78     std::unordered_set<VirtioGpuContextId> GetAttachedContexts() const;
79 
80     int Map(void** outAddress, uint64_t* outSize);
81 
82     int GetInfo(struct stream_renderer_resource_info* outInfo) const;
83 
84     int GetVulkanInfo(struct stream_renderer_vulkan_info* outInfo) const;
85 
86     int GetCaching(uint32_t* outHvaCaching) const;
87 
SetHostPipe(GoldfishHostPipe * pipe)88     void SetHostPipe(GoldfishHostPipe* pipe) { mHostPipe = pipe; }
89 
90     int WaitSyncResource();
91 
92     // Corresponds to Virtio GPU "TransferFromHost" commands and VMM requests to
93     // copy into display buffers.
94     int TransferRead(const GoldfishPipeServiceOps* ops, uint64_t offset, stream_renderer_box* box,
95                      std::optional<std::vector<struct iovec>> iovs = std::nullopt);
96 
97     struct TransferWriteResult {
98         int status = 0;
99 
100         // If, while processing the first guest to host transfer for a PIPE resource
101         // which contains the pipe service name, the returned pipe service to replace
102         // the generic pipe.
103         VirtioGpuContextId contextId = -1;
104         GoldfishHostPipe* contextPipe = nullptr;
105     };
106     // Corresponds to Virtio GPU "TransferToHost" commands.
107     TransferWriteResult TransferWrite(const GoldfishPipeServiceOps* ops, uint64_t offset,
108                                       stream_renderer_box* box,
109                                       std::optional<std::vector<struct iovec>> iovs = std::nullopt);
110 
111     int ExportBlob(struct stream_renderer_handle* outHandle);
112 
113     std::shared_ptr<RingBlob> ShareRingBlob();
114 
115 #ifdef GFXSTREAM_BUILD_WITH_SNAPSHOT_FRONTEND_SUPPORT
116     std::optional<gfxstream::host::snapshot::VirtioGpuResourceSnapshot> Snapshot() const;
117 
118     static std::optional<VirtioGpuResource> Restore(
119         const gfxstream::host::snapshot::VirtioGpuResourceSnapshot& snapshot);
120 #endif
121 
122    private:
123     int ReadFromPipeToLinear(const GoldfishPipeServiceOps* ops, uint64_t offset,
124                              stream_renderer_box* box);
125     TransferWriteResult WriteToPipeFromLinear(const GoldfishPipeServiceOps* ops, uint64_t offset,
126                                               stream_renderer_box* box);
127 
128     int ReadFromBufferToLinear(uint64_t offset, stream_renderer_box* box);
129     int WriteToBufferFromLinear(uint64_t offset, stream_renderer_box* box);
130 
131     int ReadFromColorBufferToLinear(uint64_t offset, stream_renderer_box* box);
132     int WriteToColorBufferFromLinear(uint64_t offset, stream_renderer_box* box);
133 
134     // If `iovs` provided, copy from this resource's linear buffer to the given `iovs`.
135     // Otherwise, copy from this resource's linear buffer into its previously attached
136     // iovs.
137     int TransferToIov(uint64_t offset, const stream_renderer_box* box,
138                       std::optional<std::vector<struct iovec>> iovs = std::nullopt);
139 
140     // If `iovs` provided, copy from the given `iovs` to this resources linear buffer.
141     // Otherwise, copy from this resource's previously attached iovs into its linear
142     // buffer.
143     int TransferFromIov(uint64_t offset, const stream_renderer_box* box,
144                         std::optional<std::vector<struct iovec>> iovs = std::nullopt);
145 
146     enum TransferDirection {
147         IOV_TO_LINEAR = 0,
148         LINEAR_TO_IOV = 1,
149     };
150     int TransferWithIov(uint64_t offset, const stream_renderer_box* box,
151                         const std::vector<struct iovec>& iovs, TransferDirection direction);
152 
153     // LINT.IfChange(virtio_gpu_resource)
154     VirtioGpuResourceId mId = -1;
155     VirtioGpuResourceType mResourceType = VirtioGpuResourceType::UNKNOWN;
156     std::optional<struct stream_renderer_resource_create_args> mCreateArgs;
157     std::optional<struct stream_renderer_create_blob> mCreateBlobArgs;
158     std::vector<struct iovec> mIovs;
159     std::vector<char> mLinear;
160     GoldfishHostPipe* mHostPipe = nullptr;
161     std::optional<VirtioGpuContextId> mLatestAttachedContext;
162     std::unordered_set<VirtioGpuContextId> mAttachedToContexts;
163 
164     // If this resource is a blob resource, the source of the external memory.
165     //
166     //   * For ring blobs, blobs that are used soley for guest and host
167     //     communication, the external memory is allocated by this resource
168     //     in the frontend.
169     //
170     //   * For non ring blobs, the memory from the backend as either an external
171     //     memory handle (`BlobDescriptorInfo`) or a raw mapping.
172     using RingBlobMemory = std::shared_ptr<RingBlob>;
173     using ExternalMemoryDescriptor = std::shared_ptr<BlobDescriptorInfo>;
174     using ExternalMemoryMapping = HostMemInfo;
175 
176     using BlobMemory =
177         std::variant<RingBlobMemory, ExternalMemoryDescriptor, ExternalMemoryMapping>;
178     std::optional<BlobMemory> mBlobMemory;
179     // LINT.ThenChange(VirtioGpuResourceSnapshot.proto:virtio_gpu_resource)
180 };
181 
182 }  // namespace host
183 }  // namespace gfxstream