• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 <fcntl.h>
18 #include <sys/mman.h>
19 #include <unistd.h>
20 #include <xf86drm.h>
21 #include <cerrno>
22 #include <cstring>
23 
24 #include <cutils/log.h>
25 
26 #include "VirtGpu.h"
27 #include "virtgpu_drm.h"
28 
VirtGpuBlob(int64_t deviceHandle,uint32_t blobHandle,uint32_t resourceHandle,uint64_t size)29 VirtGpuBlob::VirtGpuBlob(int64_t deviceHandle, uint32_t blobHandle, uint32_t resourceHandle,
30                          uint64_t size)
31     : mDeviceHandle(deviceHandle),
32       mBlobHandle(blobHandle),
33       mResourceHandle(resourceHandle),
34       mSize(size) {}
35 
~VirtGpuBlob(void)36 VirtGpuBlob::~VirtGpuBlob(void) {
37     struct drm_gem_close gem_close {
38         .handle = mBlobHandle, .pad = 0,
39     };
40 
41     int ret = drmIoctl(mDeviceHandle, DRM_IOCTL_GEM_CLOSE, &gem_close);
42     if (ret) {
43         ALOGE("DRM_IOCTL_GEM_CLOSE failed with : [%s, blobHandle %u, resourceHandle: %u]",
44               strerror(errno), mBlobHandle, mResourceHandle);
45     }
46 }
47 
getBlobHandle(void)48 uint32_t VirtGpuBlob::getBlobHandle(void) {
49     return mBlobHandle;
50 }
51 
getResourceHandle(void)52 uint32_t VirtGpuBlob::getResourceHandle(void) {
53     return mResourceHandle;
54 }
55 
createMapping(void)56 VirtGpuBlobMappingPtr VirtGpuBlob::createMapping(void) {
57     int ret;
58     struct drm_virtgpu_map map {
59         .handle = mBlobHandle, .pad = 0,
60     };
61 
62     ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_MAP, &map);
63     if (ret) {
64         ALOGE("DRM_IOCTL_VIRTGPU_MAP failed with %s", strerror(errno));
65         return nullptr;
66     }
67 
68     uint8_t* ptr = static_cast<uint8_t*>(
69             mmap64(nullptr, mSize, PROT_WRITE | PROT_READ, MAP_SHARED, mDeviceHandle, map.offset));
70 
71     if (ptr == MAP_FAILED) {
72         ALOGE("mmap64 failed with (%s)", strerror(errno));
73         return nullptr;
74     }
75 
76     return std::make_shared<VirtGpuBlobMapping>(shared_from_this(), ptr, mSize);
77 }
78 
exportBlob(struct VirtGpuExternalHandle & handle)79 int VirtGpuBlob::exportBlob(struct VirtGpuExternalHandle& handle) {
80     int ret, fd;
81 
82     ret = drmPrimeHandleToFD(mDeviceHandle, mBlobHandle, DRM_CLOEXEC | DRM_RDWR, &fd);
83     if (ret) {
84         ALOGE("drmPrimeHandleToFD failed with %s", strerror(errno));
85         return ret;
86     }
87 
88     handle.osHandle = static_cast<int64_t>(fd);
89     handle.type = kMemHandleDmabuf;
90     return 0;
91 }
92 
wait()93 int VirtGpuBlob::wait() {
94     int ret;
95     struct drm_virtgpu_3d_wait wait_3d = {0};
96 
97     int retry = 0;
98     do {
99         if (retry > 0 && (retry % 10 == 0)) {
100             ALOGE("DRM_IOCTL_VIRTGPU_WAIT failed with EBUSY for %d times.", retry);
101         }
102         wait_3d.handle = mBlobHandle;
103         ret = drmIoctl(mDeviceHandle, DRM_IOCTL_VIRTGPU_WAIT, &wait_3d);
104         ++retry;
105     } while (ret < 0 && errno == EBUSY);
106 
107     if (ret < 0) {
108         ALOGE("DRM_IOCTL_VIRTGPU_WAIT failed with %s", strerror(errno));
109         return ret;
110     }
111 
112     return 0;
113 }
114