blob: a36ba32369083167272b44c27b29fa48db3264a7 [file] [log] [blame]
/*
* Copyright (C) 2021 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 <inttypes.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <log/log.h>
#include <gralloc_cb_bp.h>
#include <xf86drm.h>
#include "cros_gralloc_handle.h"
#include "virtgpu_drm.h"
static bool isMinigbmFromProperty() {
static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
const auto grallocProp = android::base::GetProperty(kGrallocProp, "");
ALOGD("%s:codecs: minigbm query prop value is: %s", __FUNCTION__, grallocProp.c_str());
if (grallocProp == "minigbm") {
ALOGD("%s:codecs: Using minigbm, in minigbm mode.\n", __FUNCTION__);
return true;
} else {
ALOGD("%s:codecs: Is not using minigbm, in goldfish mode.\n", __FUNCTION__);
return false;
}
}
class ColorBufferUtilsGlobalState {
public:
ColorBufferUtilsGlobalState() {
m_isMinigbm = isMinigbmFromProperty();
if (m_isMinigbm) {
static constexpr int kRendernodeMinor = 128;
m_rendernodeFd = drmOpenRender(kRendernodeMinor);
}
}
uint32_t getColorBufferHandle(native_handle_t const* handle) {
if (m_isMinigbm) {
struct drm_virtgpu_resource_info info;
if (!getResInfo(handle, &info)) {
ALOGE("%s: Error gtting color buffer handle (minigbm case)", __func__);
return -1;
}
return info.res_handle;
} else {
return cb_handle_t::from(handle)->hostHandle;
}
}
private:
bool getResInfo(native_handle_t const* handle,
struct drm_virtgpu_resource_info* info) {
memset(info, 0x0, sizeof(*info));
if (m_rendernodeFd < 0) {
ALOGE("%s: Error, rendernode fd missing\n", __func__);
return false;
}
struct drm_gem_close gem_close;
memset(&gem_close, 0x0, sizeof(gem_close));
cros_gralloc_handle const* cros_handle =
reinterpret_cast<cros_gralloc_handle const*>(handle);
uint32_t prime_handle;
int ret = drmPrimeFDToHandle(m_rendernodeFd, cros_handle->fds[0], &prime_handle);
if (ret) {
ALOGE("%s: DRM_IOCTL_PRIME_FD_TO_HANDLE failed: %s (errno %d)\n",
__func__, strerror(errno), errno);
return false;
}
info->bo_handle = prime_handle;
gem_close.handle = prime_handle;
ret = drmIoctl(m_rendernodeFd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, info);
if (ret) {
ALOGE("%s: DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed: %s (errno %d)\n",
__func__, strerror(errno), errno);
drmIoctl(m_rendernodeFd, DRM_IOCTL_GEM_CLOSE, &gem_close);
return false;
}
drmIoctl(m_rendernodeFd, DRM_IOCTL_GEM_CLOSE, &gem_close);
return true;
}
bool m_isMinigbm;
int m_rendernodeFd = -1; // to be closed when this process dies
};
static ColorBufferUtilsGlobalState* getGlobals() {
static ColorBufferUtilsGlobalState* globals = new ColorBufferUtilsGlobalState;
return globals;
}
uint32_t getColorBufferHandle(native_handle_t const* handle) {
return getGlobals()->getColorBufferHandle(handle);
}