1 /*
2 * Copyright (C) 2021 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 #include <inttypes.h>
17 #include <android-base/parseint.h>
18 #include <android-base/properties.h>
19 #include <android-base/strings.h>
20 #include <log/log.h>
21 #include <gralloc_cb_bp.h>
22 #include <drm/virtgpu_drm.h>
23 #include <xf86drm.h>
24
25 #include "cros_gralloc_handle.h"
26
isMinigbmFromProperty()27 static bool isMinigbmFromProperty() {
28 static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
29
30 const auto grallocProp = android::base::GetProperty(kGrallocProp, "");
31 ALOGD("%s:codecs: minigbm query prop value is: %s", __FUNCTION__, grallocProp.c_str());
32
33 if (grallocProp == "minigbm") {
34 ALOGD("%s:codecs: Using minigbm, in minigbm mode.\n", __FUNCTION__);
35 return true;
36 } else {
37 ALOGD("%s:codecs: Is not using minigbm, in goldfish mode.\n", __FUNCTION__);
38 return false;
39 }
40 }
41
42 class ColorBufferUtilsGlobalState {
43 public:
ColorBufferUtilsGlobalState()44 ColorBufferUtilsGlobalState() {
45 m_isMinigbm = isMinigbmFromProperty();
46
47 if (m_isMinigbm) {
48 static constexpr int kRendernodeMinor = 128;
49 m_rendernodeFd = drmOpenRender(kRendernodeMinor);
50 }
51 }
52
getColorBufferHandle(native_handle_t const * handle)53 uint32_t getColorBufferHandle(native_handle_t const* handle) {
54 if (m_isMinigbm) {
55 struct drm_virtgpu_resource_info info;
56 if (!getResInfo(handle, &info)) {
57 ALOGE("%s: Error gtting color buffer handle (minigbm case)", __func__);
58 return -1;
59 }
60 return info.res_handle;
61 } else {
62 return cb_handle_t::from(handle)->hostHandle;
63 }
64 }
65
66 private:
67
getResInfo(native_handle_t const * handle,struct drm_virtgpu_resource_info * info)68 bool getResInfo(native_handle_t const* handle,
69 struct drm_virtgpu_resource_info* info) {
70 memset(info, 0x0, sizeof(*info));
71 if (m_rendernodeFd < 0) {
72 ALOGE("%s: Error, rendernode fd missing\n", __func__);
73 return false;
74 }
75
76 struct drm_gem_close gem_close;
77 memset(&gem_close, 0x0, sizeof(gem_close));
78
79 cros_gralloc_handle const* cros_handle =
80 reinterpret_cast<cros_gralloc_handle const*>(handle);
81
82 uint32_t prime_handle;
83 int ret = drmPrimeFDToHandle(m_rendernodeFd, cros_handle->fds[0], &prime_handle);
84 if (ret) {
85 ALOGE("%s: DRM_IOCTL_PRIME_FD_TO_HANDLE failed: %s (errno %d)\n",
86 __func__, strerror(errno), errno);
87 return false;
88 }
89
90 info->bo_handle = prime_handle;
91 gem_close.handle = prime_handle;
92
93 ret = drmIoctl(m_rendernodeFd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, info);
94 if (ret) {
95 ALOGE("%s: DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed: %s (errno %d)\n",
96 __func__, strerror(errno), errno);
97 drmIoctl(m_rendernodeFd, DRM_IOCTL_GEM_CLOSE, &gem_close);
98 return false;
99 }
100
101 drmIoctl(m_rendernodeFd, DRM_IOCTL_GEM_CLOSE, &gem_close);
102 return true;
103 }
104
105 bool m_isMinigbm;
106 int m_rendernodeFd = -1; // to be closed when this process dies
107 };
108
getGlobals()109 static ColorBufferUtilsGlobalState* getGlobals() {
110 static ColorBufferUtilsGlobalState* globals = new ColorBufferUtilsGlobalState;
111 return globals;
112 }
113
getColorBufferHandle(native_handle_t const * handle)114 uint32_t getColorBufferHandle(native_handle_t const* handle) {
115 return getGlobals()->getColorBufferHandle(handle);
116 }
117