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 <xf86drm.h>
23
24 #include <C2AllocatorGralloc.h>
25
26 #include "cros_gralloc_handle.h"
27 #include "virtgpu_drm.h"
28
isMinigbmFromProperty()29 static bool isMinigbmFromProperty() {
30 static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
31
32 const auto grallocProp = android::base::GetProperty(kGrallocProp, "");
33 ALOGD("%s:codecs: minigbm query prop value is: %s", __FUNCTION__, grallocProp.c_str());
34
35 if (grallocProp == "minigbm") {
36 ALOGD("%s:codecs: Using minigbm, in minigbm mode.\n", __FUNCTION__);
37 return true;
38 } else {
39 ALOGD("%s:codecs: Is not using minigbm, in goldfish mode.\n", __FUNCTION__);
40 return false;
41 }
42 }
43
44 class ColorBufferUtilsGlobalState {
45 public:
ColorBufferUtilsGlobalState()46 ColorBufferUtilsGlobalState() {
47 m_isMinigbm = isMinigbmFromProperty();
48
49 if (m_isMinigbm) {
50 static constexpr int kRendernodeMinor = 128;
51 m_rendernodeFd = drmOpenRender(kRendernodeMinor);
52 }
53 }
54
getColorBufferHandle(native_handle_t const * handle)55 uint32_t getColorBufferHandle(native_handle_t const* handle) {
56 if (m_isMinigbm) {
57 struct drm_virtgpu_resource_info info;
58 if (!getResInfo(handle, &info)) {
59 ALOGE("%s: Error gtting color buffer handle (minigbm case)", __func__);
60 return -1;
61 }
62 return info.res_handle;
63 } else {
64 return cb_handle_t::from(handle)->hostHandle;
65 }
66 }
67
getClientUsage(const std::shared_ptr<C2BlockPool> & pool)68 uint64_t getClientUsage(const std::shared_ptr<C2BlockPool> &pool) {
69 std::shared_ptr<C2GraphicBlock> myOutBlock;
70 const C2MemoryUsage usage = {0, 0};
71 const uint32_t format = HAL_PIXEL_FORMAT_YCBCR_420_888;
72 pool->fetchGraphicBlock(2, 2, format, usage, &myOutBlock);
73 auto myc2Handle = myOutBlock->handle();
74 native_handle_t *mygrallocHandle =
75 android::UnwrapNativeCodec2GrallocHandle(myc2Handle);
76 if (m_isMinigbm) {
77 cros_gralloc_handle const* cros_handle =
78 reinterpret_cast<cros_gralloc_handle const*>(mygrallocHandle);
79 return cros_handle->usage;
80 } else {
81 cb_handle_t* mycb = (cb_handle_t*)(mygrallocHandle);
82 return mycb->usage;
83 }
84 }
85
86 private:
87
getResInfo(native_handle_t const * handle,struct drm_virtgpu_resource_info * info)88 bool getResInfo(native_handle_t const* handle,
89 struct drm_virtgpu_resource_info* info) {
90 memset(info, 0x0, sizeof(*info));
91 if (m_rendernodeFd < 0) {
92 ALOGE("%s: Error, rendernode fd missing\n", __func__);
93 return false;
94 }
95
96 struct drm_gem_close gem_close;
97 memset(&gem_close, 0x0, sizeof(gem_close));
98
99 cros_gralloc_handle const* cros_handle =
100 reinterpret_cast<cros_gralloc_handle const*>(handle);
101
102 uint32_t prime_handle;
103 int ret = drmPrimeFDToHandle(m_rendernodeFd, cros_handle->fds[0], &prime_handle);
104 if (ret) {
105 ALOGE("%s: DRM_IOCTL_PRIME_FD_TO_HANDLE failed: %s (errno %d)\n",
106 __func__, strerror(errno), errno);
107 return false;
108 }
109
110 info->bo_handle = prime_handle;
111 gem_close.handle = prime_handle;
112
113 ret = drmIoctl(m_rendernodeFd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, info);
114 if (ret) {
115 ALOGE("%s: DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed: %s (errno %d)\n",
116 __func__, strerror(errno), errno);
117 drmIoctl(m_rendernodeFd, DRM_IOCTL_GEM_CLOSE, &gem_close);
118 return false;
119 }
120
121 drmIoctl(m_rendernodeFd, DRM_IOCTL_GEM_CLOSE, &gem_close);
122 return true;
123 }
124
125 bool m_isMinigbm;
126 int m_rendernodeFd = -1; // to be closed when this process dies
127 };
128
getGlobals()129 static ColorBufferUtilsGlobalState* getGlobals() {
130 static ColorBufferUtilsGlobalState* globals = new ColorBufferUtilsGlobalState;
131 return globals;
132 }
133
getColorBufferHandle(native_handle_t const * handle)134 uint32_t getColorBufferHandle(native_handle_t const* handle) {
135 return getGlobals()->getColorBufferHandle(handle);
136 }
137
getClientUsage(const std::shared_ptr<C2BlockPool> & pool)138 uint64_t getClientUsage(const std::shared_ptr<C2BlockPool> &pool) {
139 return getGlobals()->getClientUsage(pool);
140 }
141
142