mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 08:50:13 +01:00
Make VirtGpu* interfaces
... so that upcoming end2end tests can set up a mock impl that interacts with the host within-process. Reviewed-by: Aaron Ruby <aruby@blackberry.com> Acked-by: Yonggang Luo <luoyonggang@gmail.com> Acked-by: Adam Jackson <ajax@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27246>
This commit is contained in:
parent
a133a31a7b
commit
fec8e296a3
8 changed files with 515 additions and 57 deletions
34
src/gfxstream/guest/platform/VirtGpu.cpp
Normal file
34
src/gfxstream/guest/platform/VirtGpu.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "VirtGpu.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static VirtGpuDevice* sDevice = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
VirtGpuDevice* VirtGpuDevice::getInstance(enum VirtGpuCapset capset) {
|
||||
if (!sDevice) {
|
||||
sDevice = platform_internal::getPlatformVirtGpuDeviceInstance(capset);
|
||||
}
|
||||
return sDevice;
|
||||
}
|
||||
|
||||
void VirtGpuDevice::setInstanceForTesting(VirtGpuDevice* device) {
|
||||
sDevice = device;
|
||||
}
|
||||
|
|
@ -114,66 +114,49 @@ class VirtGpuBlob;
|
|||
using VirtGpuBlobPtr = std::shared_ptr<VirtGpuBlob>;
|
||||
using VirtGpuBlobMappingPtr = std::shared_ptr<VirtGpuBlobMapping>;
|
||||
|
||||
class VirtGpuBlob : public std::enable_shared_from_this<VirtGpuBlob> {
|
||||
class VirtGpuBlob {
|
||||
public:
|
||||
VirtGpuBlob(int64_t deviceHandle, uint32_t blobHandle, uint32_t resourceHandle, uint64_t size);
|
||||
~VirtGpuBlob();
|
||||
virtual ~VirtGpuBlob() {}
|
||||
|
||||
uint32_t getResourceHandle(void);
|
||||
uint32_t getBlobHandle(void);
|
||||
int wait(void);
|
||||
virtual uint32_t getResourceHandle(void) = 0;
|
||||
virtual uint32_t getBlobHandle(void) = 0;
|
||||
virtual int wait(void) = 0;
|
||||
|
||||
VirtGpuBlobMappingPtr createMapping(void);
|
||||
int exportBlob(struct VirtGpuExternalHandle& handle);
|
||||
|
||||
private:
|
||||
// Not owned. Really should use a ScopedFD for this, but doesn't matter since we have a
|
||||
// singleton deviceimplemenentation anyways.
|
||||
int64_t mDeviceHandle;
|
||||
|
||||
uint32_t mBlobHandle;
|
||||
uint32_t mResourceHandle;
|
||||
uint64_t mSize;
|
||||
virtual VirtGpuBlobMappingPtr createMapping(void) = 0;
|
||||
virtual int exportBlob(struct VirtGpuExternalHandle& handle) = 0;
|
||||
};
|
||||
|
||||
class VirtGpuBlobMapping {
|
||||
public:
|
||||
VirtGpuBlobMapping(VirtGpuBlobPtr blob, uint8_t* ptr, uint64_t size);
|
||||
~VirtGpuBlobMapping(void);
|
||||
virtual ~VirtGpuBlobMapping(void) {}
|
||||
|
||||
uint8_t* asRawPtr(void);
|
||||
|
||||
private:
|
||||
VirtGpuBlobPtr mBlob;
|
||||
uint8_t* mPtr;
|
||||
uint64_t mSize;
|
||||
virtual uint8_t* asRawPtr(void) = 0;
|
||||
};
|
||||
|
||||
class VirtGpuDevice {
|
||||
public:
|
||||
static VirtGpuDevice& getInstance(enum VirtGpuCapset capset = kCapsetNone);
|
||||
int64_t getDeviceHandle(void);
|
||||
static VirtGpuDevice* getInstance(enum VirtGpuCapset capset = kCapsetNone);
|
||||
static void setInstanceForTesting(VirtGpuDevice* device);
|
||||
|
||||
struct VirtGpuCaps getCaps(void);
|
||||
virtual ~VirtGpuDevice() {}
|
||||
|
||||
VirtGpuBlobPtr createBlob(const struct VirtGpuCreateBlob& blobCreate);
|
||||
VirtGpuBlobPtr createPipeBlob(uint32_t size);
|
||||
VirtGpuBlobPtr importBlob(const struct VirtGpuExternalHandle& handle);
|
||||
virtual int64_t getDeviceHandle(void) = 0;
|
||||
|
||||
int execBuffer(struct VirtGpuExecBuffer& execbuffer, VirtGpuBlobPtr blob);
|
||||
virtual struct VirtGpuCaps getCaps(void) = 0;
|
||||
|
||||
private:
|
||||
VirtGpuDevice(enum VirtGpuCapset capset);
|
||||
~VirtGpuDevice();
|
||||
VirtGpuDevice(VirtGpuDevice const&);
|
||||
void operator=(VirtGpuDevice const&);
|
||||
virtual VirtGpuBlobPtr createBlob(const struct VirtGpuCreateBlob& blobCreate) = 0;
|
||||
virtual VirtGpuBlobPtr createPipeBlob(uint32_t size) = 0;
|
||||
virtual VirtGpuBlobPtr importBlob(const struct VirtGpuExternalHandle& handle) = 0;
|
||||
|
||||
static VirtGpuDevice mInstance;
|
||||
int64_t mDeviceHandle;
|
||||
|
||||
struct VirtGpuCaps mCaps;
|
||||
virtual int execBuffer(struct VirtGpuExecBuffer& execbuffer, VirtGpuBlobPtr blob) = 0;
|
||||
};
|
||||
|
||||
namespace platform_internal {
|
||||
|
||||
VirtGpuDevice* getPlatformVirtGpuDeviceInstance(enum VirtGpuCapset capset = kCapsetNone);
|
||||
|
||||
} // namespace platform_internal
|
||||
|
||||
// HACK: We can use android::base::EnumFlags, but we'll have to do more guest
|
||||
// refactorings to figure out our end goal. We can either depend more on base or
|
||||
// try to transition to something else (b:202552093) [atleast for guests].
|
||||
|
|
|
|||
75
src/gfxstream/guest/platform/linux/LinuxVirtGpu.h
Normal file
75
src/gfxstream/guest/platform/linux/LinuxVirtGpu.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* 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
|
||||
|
||||
#include "VirtGpu.h"
|
||||
|
||||
class LinuxVirtGpuBlob : public std::enable_shared_from_this<LinuxVirtGpuBlob>, public VirtGpuBlob {
|
||||
public:
|
||||
LinuxVirtGpuBlob(int64_t deviceHandle, uint32_t blobHandle, uint32_t resourceHandle, uint64_t size);
|
||||
~LinuxVirtGpuBlob();
|
||||
|
||||
uint32_t getResourceHandle(void) override;
|
||||
uint32_t getBlobHandle(void) override;
|
||||
int wait(void) override;
|
||||
|
||||
VirtGpuBlobMappingPtr createMapping(void) override;
|
||||
int exportBlob(struct VirtGpuExternalHandle& handle) override;
|
||||
|
||||
private:
|
||||
// Not owned. Really should use a ScopedFD for this, but doesn't matter since we have a
|
||||
// singleton deviceimplemenentation anyways.
|
||||
int64_t mDeviceHandle;
|
||||
|
||||
uint32_t mBlobHandle;
|
||||
uint32_t mResourceHandle;
|
||||
uint64_t mSize;
|
||||
};
|
||||
|
||||
class LinuxVirtGpuBlobMapping : public VirtGpuBlobMapping {
|
||||
public:
|
||||
LinuxVirtGpuBlobMapping(VirtGpuBlobPtr blob, uint8_t* ptr, uint64_t size);
|
||||
~LinuxVirtGpuBlobMapping(void);
|
||||
|
||||
uint8_t* asRawPtr(void) override;
|
||||
|
||||
private:
|
||||
VirtGpuBlobPtr mBlob;
|
||||
uint8_t* mPtr;
|
||||
uint64_t mSize;
|
||||
};
|
||||
|
||||
class LinuxVirtGpuDevice : public VirtGpuDevice {
|
||||
public:
|
||||
LinuxVirtGpuDevice(enum VirtGpuCapset capset);
|
||||
virtual ~LinuxVirtGpuDevice();
|
||||
|
||||
virtual int64_t getDeviceHandle(void);
|
||||
|
||||
virtual struct VirtGpuCaps getCaps(void);
|
||||
|
||||
virtual VirtGpuBlobPtr createBlob(const struct VirtGpuCreateBlob& blobCreate);
|
||||
virtual VirtGpuBlobPtr createPipeBlob(uint32_t size);
|
||||
virtual VirtGpuBlobPtr importBlob(const struct VirtGpuExternalHandle& handle);
|
||||
|
||||
virtual int execBuffer(struct VirtGpuExecBuffer& execbuffer, VirtGpuBlobPtr blob);
|
||||
|
||||
private:
|
||||
int64_t mDeviceHandle;
|
||||
|
||||
struct VirtGpuCaps mCaps;
|
||||
};
|
||||
113
src/gfxstream/guest/platform/linux/LinuxVirtGpuBlob.cpp
Normal file
113
src/gfxstream/guest/platform/linux/LinuxVirtGpuBlob.cpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "LinuxVirtGpu.h"
|
||||
#include "virtgpu_drm.h"
|
||||
|
||||
LinuxVirtGpuBlob::LinuxVirtGpuBlob(int64_t deviceHandle, uint32_t blobHandle, uint32_t resourceHandle,
|
||||
uint64_t size)
|
||||
: mDeviceHandle(deviceHandle),
|
||||
mBlobHandle(blobHandle),
|
||||
mResourceHandle(resourceHandle),
|
||||
mSize(size) {}
|
||||
|
||||
LinuxVirtGpuBlob::~LinuxVirtGpuBlob(void) {
|
||||
struct drm_gem_close gem_close {
|
||||
.handle = mBlobHandle, .pad = 0,
|
||||
};
|
||||
|
||||
int ret = drmIoctl(mDeviceHandle, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
if (ret) {
|
||||
ALOGE("DRM_IOCTL_GEM_CLOSE failed with : [%s, blobHandle %u, resourceHandle: %u]",
|
||||
strerror(errno), mBlobHandle, mResourceHandle);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t LinuxVirtGpuBlob::getBlobHandle(void) {
|
||||
return mBlobHandle;
|
||||
}
|
||||
|
||||
uint32_t LinuxVirtGpuBlob::getResourceHandle(void) {
|
||||
return mResourceHandle;
|
||||
}
|
||||
|
||||
VirtGpuBlobMappingPtr LinuxVirtGpuBlob::createMapping(void) {
|
||||
int ret;
|
||||
struct drm_virtgpu_map map {
|
||||
.handle = mBlobHandle, .pad = 0,
|
||||
};
|
||||
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_MAP, &map);
|
||||
if (ret) {
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_MAP failed with %s", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t* ptr = static_cast<uint8_t*>(
|
||||
mmap64(nullptr, mSize, PROT_WRITE | PROT_READ, MAP_SHARED, mDeviceHandle, map.offset));
|
||||
|
||||
if (ptr == MAP_FAILED) {
|
||||
ALOGE("mmap64 failed with (%s)", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<LinuxVirtGpuBlobMapping>(shared_from_this(), ptr, mSize);
|
||||
}
|
||||
|
||||
int LinuxVirtGpuBlob::exportBlob(struct VirtGpuExternalHandle& handle) {
|
||||
int ret, fd;
|
||||
|
||||
ret = drmPrimeHandleToFD(mDeviceHandle, mBlobHandle, DRM_CLOEXEC | DRM_RDWR, &fd);
|
||||
if (ret) {
|
||||
ALOGE("drmPrimeHandleToFD failed with %s", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
handle.osHandle = static_cast<int64_t>(fd);
|
||||
handle.type = kMemHandleDmabuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxVirtGpuBlob::wait() {
|
||||
int ret;
|
||||
struct drm_virtgpu_3d_wait wait_3d = {0};
|
||||
|
||||
int retry = 0;
|
||||
do {
|
||||
if (retry > 0 && (retry % 10 == 0)) {
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_WAIT failed with EBUSY for %d times.", retry);
|
||||
}
|
||||
wait_3d.handle = mBlobHandle;
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_WAIT, &wait_3d);
|
||||
++retry;
|
||||
} while (ret < 0 && errno == EBUSY);
|
||||
|
||||
if (ret < 0) {
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_WAIT failed with %s", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "LinuxVirtGpu.h"
|
||||
|
||||
LinuxVirtGpuBlobMapping::LinuxVirtGpuBlobMapping(VirtGpuBlobPtr blob, uint8_t* ptr, uint64_t size)
|
||||
: mBlob(blob), mPtr(ptr), mSize(size) {}
|
||||
|
||||
LinuxVirtGpuBlobMapping::~LinuxVirtGpuBlobMapping(void) {
|
||||
munmap(mPtr, mSize);
|
||||
}
|
||||
|
||||
uint8_t* LinuxVirtGpuBlobMapping::asRawPtr(void) {
|
||||
return mPtr;
|
||||
}
|
||||
222
src/gfxstream/guest/platform/linux/LinuxVirtGpuDevice.cpp
Normal file
222
src/gfxstream/guest/platform/linux/LinuxVirtGpuDevice.cpp
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "LinuxVirtGpu.h"
|
||||
#include "virtgpu_drm.h"
|
||||
#include "virtgpu_gfxstream_protocol.h"
|
||||
|
||||
#define PARAM(x) \
|
||||
(struct VirtGpuParam) { x, #x, 0 }
|
||||
|
||||
// See virgl_hw.h and p_defines.h
|
||||
#define VIRGL_FORMAT_R8_UNORM 64
|
||||
#define VIRGL_BIND_CUSTOM (1 << 17)
|
||||
#define PIPE_BUFFER 0
|
||||
|
||||
LinuxVirtGpuDevice::LinuxVirtGpuDevice(enum VirtGpuCapset capset) {
|
||||
struct VirtGpuParam params[] = {
|
||||
PARAM(VIRTGPU_PARAM_3D_FEATURES), PARAM(VIRTGPU_PARAM_CAPSET_QUERY_FIX),
|
||||
PARAM(VIRTGPU_PARAM_RESOURCE_BLOB), PARAM(VIRTGPU_PARAM_HOST_VISIBLE),
|
||||
PARAM(VIRTGPU_PARAM_CROSS_DEVICE), PARAM(VIRTGPU_PARAM_CONTEXT_INIT),
|
||||
PARAM(VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs), PARAM(VIRTGPU_PARAM_CREATE_GUEST_HANDLE),
|
||||
};
|
||||
|
||||
int ret;
|
||||
struct drm_virtgpu_get_caps get_caps = {0};
|
||||
struct drm_virtgpu_context_init init = {0};
|
||||
struct drm_virtgpu_context_set_param ctx_set_params[2] = {{0}};
|
||||
|
||||
memset(&mCaps, 0, sizeof(struct VirtGpuCaps));
|
||||
|
||||
mDeviceHandle = static_cast<int64_t>(drmOpenRender(128));
|
||||
if (mDeviceHandle < 0) {
|
||||
ALOGE("Failed to open rendernode: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < kParamMax; i++) {
|
||||
struct drm_virtgpu_getparam get_param = {0};
|
||||
get_param.param = params[i].param;
|
||||
get_param.value = (uint64_t)(uintptr_t)¶ms[i].value;
|
||||
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_GETPARAM, &get_param);
|
||||
if (ret) {
|
||||
ALOGE("virtgpu backend not enabling %s", params[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
mCaps.params[i] = params[i].value;
|
||||
}
|
||||
|
||||
get_caps.cap_set_id = static_cast<uint32_t>(capset);
|
||||
if (capset == kCapsetGfxStreamVulkan) {
|
||||
get_caps.size = sizeof(struct gfxstreamCapset);
|
||||
get_caps.addr = (unsigned long long)&mCaps.gfxstreamCapset;
|
||||
}
|
||||
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_GET_CAPS, &get_caps);
|
||||
if (ret) {
|
||||
// Don't fail get capabilities just yet, AEMU doesn't use this API
|
||||
// yet (b/272121235);
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s", strerror(errno));
|
||||
}
|
||||
|
||||
// We always need an ASG blob in some cases, so always define blobAlignment
|
||||
if (!mCaps.gfxstreamCapset.blobAlignment) {
|
||||
mCaps.gfxstreamCapset.blobAlignment = 4096;
|
||||
}
|
||||
|
||||
ctx_set_params[0].param = VIRTGPU_CONTEXT_PARAM_NUM_RINGS;
|
||||
ctx_set_params[0].value = 2;
|
||||
init.num_params = 1;
|
||||
|
||||
if (capset != kCapsetNone) {
|
||||
ctx_set_params[1].param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID;
|
||||
ctx_set_params[1].value = static_cast<uint32_t>(capset);
|
||||
init.num_params++;
|
||||
}
|
||||
|
||||
init.ctx_set_params = (unsigned long long)&ctx_set_params[0];
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_CONTEXT_INIT, &init);
|
||||
if (ret) {
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_CONTEXT_INIT failed with %s, continuing without context...",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
LinuxVirtGpuDevice::~LinuxVirtGpuDevice() {
|
||||
close(mDeviceHandle);
|
||||
}
|
||||
|
||||
struct VirtGpuCaps LinuxVirtGpuDevice::getCaps(void) { return mCaps; }
|
||||
|
||||
int64_t LinuxVirtGpuDevice::getDeviceHandle(void) {
|
||||
return mDeviceHandle;
|
||||
}
|
||||
|
||||
VirtGpuBlobPtr LinuxVirtGpuDevice::createPipeBlob(uint32_t size) {
|
||||
drm_virtgpu_resource_create create = {
|
||||
.target = PIPE_BUFFER,
|
||||
.format = VIRGL_FORMAT_R8_UNORM,
|
||||
.bind = VIRGL_BIND_CUSTOM,
|
||||
.width = size,
|
||||
.height = 1U,
|
||||
.depth = 1U,
|
||||
.array_size = 0U,
|
||||
.size = size,
|
||||
.stride = size,
|
||||
};
|
||||
|
||||
int ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &create);
|
||||
if (ret) {
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_RESOURCE_CREATE failed with %s", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<LinuxVirtGpuBlob>(mDeviceHandle, create.bo_handle, create.res_handle,
|
||||
static_cast<uint64_t>(size));
|
||||
}
|
||||
|
||||
VirtGpuBlobPtr LinuxVirtGpuDevice::createBlob(const struct VirtGpuCreateBlob& blobCreate) {
|
||||
int ret;
|
||||
struct drm_virtgpu_resource_create_blob create = {0};
|
||||
|
||||
create.size = blobCreate.size;
|
||||
create.blob_mem = blobCreate.blobMem;
|
||||
create.blob_flags = blobCreate.flags;
|
||||
create.blob_id = blobCreate.blobId;
|
||||
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &create);
|
||||
if (ret < 0) {
|
||||
ALOGE("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<LinuxVirtGpuBlob>(mDeviceHandle, create.bo_handle, create.res_handle,
|
||||
blobCreate.size);
|
||||
}
|
||||
|
||||
VirtGpuBlobPtr LinuxVirtGpuDevice::importBlob(const struct VirtGpuExternalHandle& handle) {
|
||||
struct drm_virtgpu_resource_info info = {0};
|
||||
uint32_t blobHandle;
|
||||
int ret;
|
||||
|
||||
ret = drmPrimeFDToHandle(mDeviceHandle, handle.osHandle, &blobHandle);
|
||||
close(handle.osHandle);
|
||||
if (ret) {
|
||||
ALOGE("DRM_IOCTL_PRIME_FD_TO_HANDLE failed: %s", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
info.bo_handle = blobHandle;
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, &info);
|
||||
if (ret) {
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed: %s", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<LinuxVirtGpuBlob>(mDeviceHandle, blobHandle, info.res_handle,
|
||||
static_cast<uint64_t>(info.size));
|
||||
}
|
||||
|
||||
int LinuxVirtGpuDevice::execBuffer(struct VirtGpuExecBuffer& execbuffer, VirtGpuBlobPtr blob) {
|
||||
int ret;
|
||||
struct drm_virtgpu_execbuffer exec = {0};
|
||||
uint32_t blobHandle;
|
||||
|
||||
exec.flags = execbuffer.flags;
|
||||
exec.size = execbuffer.command_size;
|
||||
exec.ring_idx = execbuffer.ring_idx;
|
||||
exec.command = (uint64_t)(uintptr_t)(execbuffer.command);
|
||||
exec.fence_fd = -1;
|
||||
|
||||
if (blob) {
|
||||
blobHandle = blob->getBlobHandle();
|
||||
exec.bo_handles = (uint64_t)(uintptr_t)(&blobHandle);
|
||||
exec.num_bo_handles = 1;
|
||||
}
|
||||
|
||||
ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_EXECBUFFER, &exec);
|
||||
if (ret) {
|
||||
ALOGE("DRM_IOCTL_VIRTGPU_EXECBUFFER failed: %s", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (execbuffer.flags & kFenceOut) {
|
||||
execbuffer.handle.osHandle = exec.fence_fd;
|
||||
execbuffer.handle.type = kFenceHandleSyncFd;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace platform_internal {
|
||||
|
||||
VirtGpuDevice* getPlatformVirtGpuDeviceInstance(enum VirtGpuCapset capset) {
|
||||
static LinuxVirtGpuDevice sInstance(capset);
|
||||
return &sInstance;
|
||||
}
|
||||
|
||||
} // namespace platform_internal
|
||||
|
|
@ -2,9 +2,10 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
|
||||
files_lib_platform = files(
|
||||
'VirtGpuDevice.cpp',
|
||||
'VirtGpuBlobMapping.cpp',
|
||||
'VirtGpuBlob.cpp',
|
||||
'../VirtGpu.cpp',
|
||||
'LinuxVirtGpuDevice.cpp',
|
||||
'LinuxVirtGpuBlobMapping.cpp',
|
||||
'LinuxVirtGpuBlob.cpp',
|
||||
)
|
||||
|
||||
lib_platform = static_library(
|
||||
|
|
|
|||
|
|
@ -912,8 +912,8 @@ public:
|
|||
}
|
||||
|
||||
void setupCaps(void) {
|
||||
VirtGpuDevice& instance = VirtGpuDevice::getInstance((enum VirtGpuCapset)3);
|
||||
mCaps = instance.getCaps();
|
||||
VirtGpuDevice* instance = VirtGpuDevice::getInstance((enum VirtGpuCapset)3);
|
||||
mCaps = instance->getCaps();
|
||||
|
||||
// Delete once goldfish Linux drivers are gone
|
||||
if (mCaps.gfxstreamCapset.protocolVersion == 0) {
|
||||
|
|
@ -2947,13 +2947,13 @@ public:
|
|||
}
|
||||
{
|
||||
AutoLock<RecursiveLock> lock(mLock);
|
||||
VirtGpuDevice& instance = VirtGpuDevice::getInstance((enum VirtGpuCapset)3);
|
||||
VirtGpuDevice* instance = VirtGpuDevice::getInstance((enum VirtGpuCapset)3);
|
||||
createBlob.blobMem = kBlobMemHost3d;
|
||||
createBlob.flags = kBlobFlagMappable;
|
||||
createBlob.blobId = hvaSizeId[2];
|
||||
createBlob.size = hostAllocationInfo.allocationSize;
|
||||
|
||||
auto blob = instance.createBlob(createBlob);
|
||||
auto blob = instance->createBlob(createBlob);
|
||||
if (!blob) {
|
||||
ALOGE("Failed to create coherent memory: failed to create blob.");
|
||||
res = VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||
|
|
@ -3040,7 +3040,7 @@ public:
|
|||
if (mCaps.params[kParamCreateGuestHandle]) {
|
||||
struct VirtGpuCreateBlob createBlob = {0};
|
||||
struct VirtGpuExecBuffer exec = {};
|
||||
VirtGpuDevice& instance = VirtGpuDevice::getInstance();
|
||||
VirtGpuDevice* instance = VirtGpuDevice::getInstance();
|
||||
struct gfxstreamPlaceholderCommandVk placeholderCmd = {};
|
||||
|
||||
createBlobInfo.blobId = ++mBlobId;
|
||||
|
|
@ -3053,7 +3053,7 @@ public:
|
|||
createBlob.blobId = createBlobInfo.blobId;
|
||||
createBlob.size = hostAllocationInfo.allocationSize;
|
||||
|
||||
guestBlob = instance.createBlob(createBlob);
|
||||
guestBlob = instance->createBlob(createBlob);
|
||||
if (!guestBlob) {
|
||||
ALOGE("Failed to allocate coherent memory: failed to create blob.");
|
||||
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||
|
|
@ -3064,7 +3064,7 @@ public:
|
|||
exec.command_size = sizeof(placeholderCmd);
|
||||
exec.flags = kRingIdx;
|
||||
exec.ring_idx = 1;
|
||||
if (instance.execBuffer(exec, guestBlob)) {
|
||||
if (instance->execBuffer(exec, guestBlob)) {
|
||||
ALOGE("Failed to allocate coherent memory: failed to execbuffer for wait.");
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
|
@ -3947,7 +3947,7 @@ public:
|
|||
if (info.blobId && !info.coherentMemory && !mCaps.params[kParamCreateGuestHandle]) {
|
||||
VkEncoder* enc = (VkEncoder*)context;
|
||||
VirtGpuBlobMappingPtr mapping;
|
||||
VirtGpuDevice& instance = VirtGpuDevice::getInstance();
|
||||
VirtGpuDevice* instance = VirtGpuDevice::getInstance();
|
||||
|
||||
uint64_t offset;
|
||||
uint8_t* ptr;
|
||||
|
|
@ -3961,7 +3961,7 @@ public:
|
|||
createBlob.blobId = info.blobId;
|
||||
createBlob.size = info.coherentMemorySize;
|
||||
|
||||
auto blob = instance.createBlob(createBlob);
|
||||
auto blob = instance->createBlob(createBlob);
|
||||
if (!blob) return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||
|
||||
mapping = blob->createMapping();
|
||||
|
|
@ -4613,7 +4613,7 @@ public:
|
|||
VkResult createFence(VkDevice device, uint64_t hostFenceHandle, int64_t& osHandle) {
|
||||
struct VirtGpuExecBuffer exec = { };
|
||||
struct gfxstreamCreateExportSyncVK exportSync = { };
|
||||
VirtGpuDevice& instance = VirtGpuDevice::getInstance();
|
||||
VirtGpuDevice* instance = VirtGpuDevice::getInstance();
|
||||
|
||||
uint64_t hostDeviceHandle = get_host_u64_VkDevice(device);
|
||||
|
||||
|
|
@ -4626,7 +4626,7 @@ public:
|
|||
exec.command = static_cast<void*>(&exportSync);
|
||||
exec.command_size = sizeof(exportSync);
|
||||
exec.flags = kFenceOut | kRingIdx;
|
||||
if (instance.execBuffer(exec, nullptr))
|
||||
if (instance->execBuffer(exec, nullptr))
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
|
||||
osHandle = exec.handle.osHandle;
|
||||
|
|
@ -7153,7 +7153,7 @@ public:
|
|||
if (mFeatureInfo->hasVirtioGpuNativeSync) {
|
||||
struct VirtGpuExecBuffer exec = { };
|
||||
struct gfxstreamCreateQSRIExportVK exportQSRI = { };
|
||||
VirtGpuDevice& instance = VirtGpuDevice::getInstance();
|
||||
VirtGpuDevice* instance = VirtGpuDevice::getInstance();
|
||||
|
||||
uint64_t hostImageHandle = get_host_u64_VkImage(image);
|
||||
|
||||
|
|
@ -7164,7 +7164,7 @@ public:
|
|||
exec.command = static_cast<void*>(&exportQSRI);
|
||||
exec.command_size = sizeof(exportQSRI);
|
||||
exec.flags = kFenceOut | kRingIdx;
|
||||
if (instance.execBuffer(exec, nullptr))
|
||||
if (instance->execBuffer(exec, nullptr))
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
|
||||
*fd = exec.handle.osHandle;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue