1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2023 Google
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include "VirtioGpuAddressSpaceStream.h"
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include <errno.h>
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker #include "util/log.h"
11*61046927SAndroid Build Coastguard Worker 
GetRingParamsFromCapset(enum VirtGpuCapset capset,const VirtGpuCaps & caps,uint32_t & ringSize,uint32_t & bufferSize,uint32_t & blobAlignment)12*61046927SAndroid Build Coastguard Worker static bool GetRingParamsFromCapset(enum VirtGpuCapset capset, const VirtGpuCaps& caps,
13*61046927SAndroid Build Coastguard Worker                                     uint32_t& ringSize, uint32_t& bufferSize,
14*61046927SAndroid Build Coastguard Worker                                     uint32_t& blobAlignment) {
15*61046927SAndroid Build Coastguard Worker     switch (capset) {
16*61046927SAndroid Build Coastguard Worker         case kCapsetGfxStreamVulkan:
17*61046927SAndroid Build Coastguard Worker             ringSize = caps.vulkanCapset.ringSize;
18*61046927SAndroid Build Coastguard Worker             bufferSize = caps.vulkanCapset.bufferSize;
19*61046927SAndroid Build Coastguard Worker             blobAlignment = caps.vulkanCapset.blobAlignment;
20*61046927SAndroid Build Coastguard Worker             break;
21*61046927SAndroid Build Coastguard Worker         case kCapsetGfxStreamMagma:
22*61046927SAndroid Build Coastguard Worker             ringSize = caps.magmaCapset.ringSize;
23*61046927SAndroid Build Coastguard Worker             bufferSize = caps.magmaCapset.bufferSize;
24*61046927SAndroid Build Coastguard Worker             blobAlignment = caps.magmaCapset.blobAlignment;
25*61046927SAndroid Build Coastguard Worker             break;
26*61046927SAndroid Build Coastguard Worker         case kCapsetGfxStreamGles:
27*61046927SAndroid Build Coastguard Worker             ringSize = caps.glesCapset.ringSize;
28*61046927SAndroid Build Coastguard Worker             bufferSize = caps.glesCapset.bufferSize;
29*61046927SAndroid Build Coastguard Worker             blobAlignment = caps.glesCapset.blobAlignment;
30*61046927SAndroid Build Coastguard Worker             break;
31*61046927SAndroid Build Coastguard Worker         case kCapsetGfxStreamComposer:
32*61046927SAndroid Build Coastguard Worker             ringSize = caps.composerCapset.ringSize;
33*61046927SAndroid Build Coastguard Worker             bufferSize = caps.composerCapset.bufferSize;
34*61046927SAndroid Build Coastguard Worker             blobAlignment = caps.composerCapset.blobAlignment;
35*61046927SAndroid Build Coastguard Worker             break;
36*61046927SAndroid Build Coastguard Worker         default:
37*61046927SAndroid Build Coastguard Worker             return false;
38*61046927SAndroid Build Coastguard Worker     }
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker     return true;
41*61046927SAndroid Build Coastguard Worker }
42*61046927SAndroid Build Coastguard Worker 
virtgpu_address_space_open()43*61046927SAndroid Build Coastguard Worker address_space_handle_t virtgpu_address_space_open() {
44*61046927SAndroid Build Coastguard Worker     return (address_space_handle_t)(-EINVAL);
45*61046927SAndroid Build Coastguard Worker }
46*61046927SAndroid Build Coastguard Worker 
virtgpu_address_space_close(address_space_handle_t)47*61046927SAndroid Build Coastguard Worker void virtgpu_address_space_close(address_space_handle_t) {
48*61046927SAndroid Build Coastguard Worker     // Handle opened by VirtioGpuDevice wrapper
49*61046927SAndroid Build Coastguard Worker }
50*61046927SAndroid Build Coastguard Worker 
virtgpu_address_space_ping(address_space_handle_t,struct address_space_ping * info)51*61046927SAndroid Build Coastguard Worker bool virtgpu_address_space_ping(address_space_handle_t, struct address_space_ping* info) {
52*61046927SAndroid Build Coastguard Worker     int ret;
53*61046927SAndroid Build Coastguard Worker     struct VirtGpuExecBuffer exec = {};
54*61046927SAndroid Build Coastguard Worker     VirtGpuDevice* instance = VirtGpuDevice::getInstance();
55*61046927SAndroid Build Coastguard Worker     struct gfxstreamContextPing ping = {};
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker     ping.hdr.opCode = GFXSTREAM_CONTEXT_PING;
58*61046927SAndroid Build Coastguard Worker     ping.resourceId = info->resourceId;
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker     exec.command = static_cast<void*>(&ping);
61*61046927SAndroid Build Coastguard Worker     exec.command_size = sizeof(ping);
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker     ret = instance->execBuffer(exec, nullptr);
64*61046927SAndroid Build Coastguard Worker     if (ret)
65*61046927SAndroid Build Coastguard Worker         return false;
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker     return true;
68*61046927SAndroid Build Coastguard Worker }
69*61046927SAndroid Build Coastguard Worker 
createVirtioGpuAddressSpaceStream(enum VirtGpuCapset capset)70*61046927SAndroid Build Coastguard Worker AddressSpaceStream* createVirtioGpuAddressSpaceStream(enum VirtGpuCapset capset) {
71*61046927SAndroid Build Coastguard Worker     VirtGpuResourcePtr pipe, blob;
72*61046927SAndroid Build Coastguard Worker     VirtGpuResourceMappingPtr pipeMapping, blobMapping;
73*61046927SAndroid Build Coastguard Worker     struct VirtGpuExecBuffer exec = {};
74*61046927SAndroid Build Coastguard Worker     struct VirtGpuCreateBlob blobCreate = {};
75*61046927SAndroid Build Coastguard Worker     struct gfxstreamContextCreate contextCreate = {};
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker     uint32_t ringSize = 0;
78*61046927SAndroid Build Coastguard Worker     uint32_t bufferSize = 0;
79*61046927SAndroid Build Coastguard Worker     uint32_t blobAlignment = 0;
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker     char* blobAddr, *bufferPtr;
82*61046927SAndroid Build Coastguard Worker     int ret;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker     VirtGpuDevice* instance = VirtGpuDevice::getInstance();
85*61046927SAndroid Build Coastguard Worker     auto caps = instance->getCaps();
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker     if (!GetRingParamsFromCapset(capset, caps, ringSize, bufferSize, blobAlignment)) {
88*61046927SAndroid Build Coastguard Worker         mesa_loge("Failed to get ring parameters");
89*61046927SAndroid Build Coastguard Worker         return nullptr;
90*61046927SAndroid Build Coastguard Worker     }
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker     blobCreate.blobId = 0;
93*61046927SAndroid Build Coastguard Worker     blobCreate.blobMem = kBlobMemHost3d;
94*61046927SAndroid Build Coastguard Worker     blobCreate.flags = kBlobFlagMappable;
95*61046927SAndroid Build Coastguard Worker     blobCreate.size = ALIGN_POT(ringSize + bufferSize, blobAlignment);
96*61046927SAndroid Build Coastguard Worker     blob = instance->createBlob(blobCreate);
97*61046927SAndroid Build Coastguard Worker     if (!blob)
98*61046927SAndroid Build Coastguard Worker         return nullptr;
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker     // Context creation command
101*61046927SAndroid Build Coastguard Worker     contextCreate.hdr.opCode = GFXSTREAM_CONTEXT_CREATE;
102*61046927SAndroid Build Coastguard Worker     contextCreate.resourceId = blob->getResourceHandle();
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker     exec.command = static_cast<void*>(&contextCreate);
105*61046927SAndroid Build Coastguard Worker     exec.command_size = sizeof(contextCreate);
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker     ret = instance->execBuffer(exec, blob.get());
108*61046927SAndroid Build Coastguard Worker     if (ret)
109*61046927SAndroid Build Coastguard Worker         return nullptr;
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker     // Wait occurs on global timeline -- should we use context specific one?
112*61046927SAndroid Build Coastguard Worker     ret = blob->wait();
113*61046927SAndroid Build Coastguard Worker     if (ret)
114*61046927SAndroid Build Coastguard Worker         return nullptr;
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker     blobMapping = blob->createMapping();
117*61046927SAndroid Build Coastguard Worker     if (!blobMapping)
118*61046927SAndroid Build Coastguard Worker         return nullptr;
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker     blobAddr = reinterpret_cast<char*>(blobMapping->asRawPtr());
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker     bufferPtr = blobAddr + sizeof(struct asg_ring_storage);
123*61046927SAndroid Build Coastguard Worker     struct asg_context context = asg_context_create(blobAddr, bufferPtr, bufferSize);
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker     context.ring_config->transfer_mode = 1;
126*61046927SAndroid Build Coastguard Worker     context.ring_config->host_consumed_pos = 0;
127*61046927SAndroid Build Coastguard Worker     context.ring_config->guest_write_pos = 0;
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker     struct address_space_ops ops = {
130*61046927SAndroid Build Coastguard Worker         .open = virtgpu_address_space_open,
131*61046927SAndroid Build Coastguard Worker         .close = virtgpu_address_space_close,
132*61046927SAndroid Build Coastguard Worker         .ping = virtgpu_address_space_ping,
133*61046927SAndroid Build Coastguard Worker     };
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker     AddressSpaceStream* res =
136*61046927SAndroid Build Coastguard Worker         new AddressSpaceStream((address_space_handle_t)(-1), 1, context, 0, 0, ops);
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker     res->setMapping(blobMapping);
139*61046927SAndroid Build Coastguard Worker     res->setResourceId(contextCreate.resourceId);
140*61046927SAndroid Build Coastguard Worker     return res;
141*61046927SAndroid Build Coastguard Worker }
142