1 /*
2 * Copyright 2023 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
17 #include <log/log.h>
18
19 #include "RutabagaLayer.h"
20 #include "RutabagaVirtGpu.h"
21
22 namespace gfxstream {
23
RutabagaVirtGpuDevice(std::shared_ptr<EmulatedVirtioGpu> emulation,VirtGpuCapset capset)24 RutabagaVirtGpuDevice::RutabagaVirtGpuDevice(std::shared_ptr<EmulatedVirtioGpu> emulation,
25 VirtGpuCapset capset)
26 : VirtGpuDevice(capset), mEmulation(emulation), mCapset(capset) {}
27
~RutabagaVirtGpuDevice()28 RutabagaVirtGpuDevice::~RutabagaVirtGpuDevice() { mEmulation->DestroyContext(mContextId); }
29
Init()30 bool RutabagaVirtGpuDevice::Init() {
31 uint32_t capsetId = 0;
32 uint32_t capsetSize = 0;
33 uint32_t contextInit = 0;
34 uint8_t* capsetPtr = nullptr;
35
36 mCaps = {
37 .params =
38 {
39 [kParam3D] = 1,
40 [kParamCapsetFix] = 1,
41 [kParamResourceBlob] = 1,
42 [kParamHostVisible] = 1,
43 [kParamCrossDevice] = 0,
44 [kParamContextInit] = 1,
45 [kParamSupportedCapsetIds] = 0,
46 [kParamExplicitDebugName] = 0,
47 [kParamCreateGuestHandle] = 0,
48 },
49 };
50
51 capsetId = static_cast<uint32_t>(mCapset);
52 switch (mCapset) {
53 case kCapsetGfxStreamVulkan:
54 capsetSize = sizeof(struct vulkanCapset);
55 capsetPtr = reinterpret_cast<uint8_t*>(&mCaps.vulkanCapset);
56 break;
57 case kCapsetGfxStreamMagma:
58 capsetSize = sizeof(struct magmaCapset);
59 capsetPtr = reinterpret_cast<uint8_t*>(&mCaps.magmaCapset);
60 break;
61 case kCapsetGfxStreamGles:
62 capsetSize = sizeof(struct vulkanCapset);
63 capsetPtr = reinterpret_cast<uint8_t*>(&mCaps.glesCapset);
64 break;
65 case kCapsetGfxStreamComposer:
66 capsetSize = sizeof(struct vulkanCapset);
67 capsetPtr = reinterpret_cast<uint8_t*>(&mCaps.composerCapset);
68 break;
69 default:
70 capsetSize = 0;
71 }
72
73 if (capsetId != 0) {
74 bool success = mEmulation->GetCaps(capsetId, capsetSize, capsetPtr);
75 if (!success) {
76 ALOGE("Failed to capability set");
77 return false;
78 }
79 }
80
81 const auto contextIdOp = mEmulation->CreateContext(capsetId);
82 if (!contextIdOp) {
83 ALOGE("Failed to create RutabagaVirtGpuDevice: failed to create context.");
84 return false;
85 }
86
87 mContextId = *contextIdOp;
88 return true;
89 }
90
getDeviceHandle()91 int64_t RutabagaVirtGpuDevice::getDeviceHandle() { return -1; }
92
getCaps()93 VirtGpuCaps RutabagaVirtGpuDevice::getCaps() { return mCaps; }
94
createBlob(const struct VirtGpuCreateBlob & blobCreate)95 VirtGpuResourcePtr RutabagaVirtGpuDevice::createBlob(const struct VirtGpuCreateBlob& blobCreate) {
96 const auto resourceIdOpt = mEmulation->CreateBlob(
97 mContextId, static_cast<uint32_t>(blobCreate.blobMem),
98 static_cast<uint32_t>(blobCreate.flags), blobCreate.blobId, blobCreate.size);
99 if (!resourceIdOpt) {
100 return nullptr;
101 }
102
103 return VirtGpuResourcePtr(new RutabagaVirtGpuResource(
104 mEmulation, *resourceIdOpt, RutabagaVirtGpuResource::ResourceType::kBlob, mContextId));
105 }
106
createResource(uint32_t width,uint32_t height,uint32_t stride,uint32_t virglFormat,uint32_t target,uint32_t bind)107 VirtGpuResourcePtr RutabagaVirtGpuDevice::createResource(uint32_t width, uint32_t height,
108 uint32_t stride, uint32_t virglFormat,
109 uint32_t target, uint32_t bind) {
110 uint32_t size = stride * height;
111
112 const auto resourceIdOpt =
113 mEmulation->CreateVirglBlob(mContextId, width, height, virglFormat, target, bind, size);
114 if (!resourceIdOpt) {
115 return nullptr;
116 }
117
118 return VirtGpuResourcePtr(new RutabagaVirtGpuResource(
119 mEmulation, *resourceIdOpt, RutabagaVirtGpuResource::ResourceType::kPipe, mContextId));
120 }
121
execBuffer(struct VirtGpuExecBuffer & execbuffer,const VirtGpuResource * blob)122 int RutabagaVirtGpuDevice::execBuffer(struct VirtGpuExecBuffer& execbuffer,
123 const VirtGpuResource* blob) {
124 std::optional<uint32_t> blobResourceId;
125 uint32_t fenceId = 0;
126 VirtioGpuFenceFlags fenceFlags = kFlagNone;
127
128 if (blob) {
129 blobResourceId = blob->getResourceHandle();
130 }
131
132 if (execbuffer.flags & kFenceOut) {
133 fenceFlags = kFlagFence;
134 }
135
136 int ret = mEmulation->SubmitCmd(mContextId, execbuffer.command_size, execbuffer.command,
137 execbuffer.ring_idx, fenceFlags, fenceId, blobResourceId);
138
139 if (execbuffer.flags & kFenceOut) {
140 execbuffer.handle.osHandle = fenceId;
141 execbuffer.handle.type = kFenceHandleSyncFd;
142 }
143
144 return ret;
145 }
146
importBlob(const struct VirtGpuExternalHandle &)147 VirtGpuResourcePtr RutabagaVirtGpuDevice::importBlob(const struct VirtGpuExternalHandle&) {
148 ALOGE("Unimplemented %s", __FUNCTION__);
149 return nullptr;
150 }
151
152 } // namespace gfxstream
153
createPlatformVirtGpuDevice(enum VirtGpuCapset capset,int)154 VirtGpuDevice* createPlatformVirtGpuDevice(enum VirtGpuCapset capset, int) {
155 std::shared_ptr<gfxstream::EmulatedVirtioGpu> emulation = gfxstream::EmulatedVirtioGpu::Get();
156 if (!emulation) {
157 ALOGE("Failed to create RutabagaVirtGpuDevice: failed to get emulation layer.");
158 return nullptr;
159 }
160
161 auto device = new gfxstream::RutabagaVirtGpuDevice(emulation, capset);
162 bool success = device->Init();
163 if (!success) {
164 ALOGE("Failed to create RutabagaVirtGpuDevice: Init failed.");
165 delete device;
166 return nullptr;
167 }
168
169 return device;
170 }
171