android13/vendor/rockchip/hardware/interfaces/vtunnel/common/drmgralloc.cpp

714 lines
18 KiB
C++
Executable File

/*
* Copyright (C) 2018 Fuzhou Rockchip Electronics Co.Ltd.
*
* Modification based on code covered by the Apache License, Version 2.0 (the "License").
* You may not use this software except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS TO YOU ON AN "AS IS" BASIS
* AND ANY AND ALL WARRANTIES AND REPRESENTATIONS WITH RESPECT TO SUCH SOFTWARE, WHETHER EXPRESS,
* IMPLIED, STATUTORY OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF TITLE,
* NON-INFRINGEMENT, MERCHANTABILITY, SATISFACTROY QUALITY, ACCURACY OR FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.
*
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright (C) 2015 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.
*/
// #define ENABLE_DEBUG_LOG
#define LOG_TAG "drm_hwc2_gralloc"
#if USE_GRALLOC_4
#include "drmgralloc4.h"
#endif
#include "drmgralloc.h"
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
namespace android {
#define HWC2_ALOGD_IF_VERBOSE ALOGD
#define HWC2_ALOGI ALOGD
#define HWC2_ALOGE ALOGD
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_PHY_ADDR 0x08100001
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_PRIME_FD 0x08100002
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_ATTRIBUTES 0x08100004
#define GRALLOC_MODULE_PERFORM_GET_INTERNAL_FORMAT 0x08100006
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_WIDTH 0x08100008
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_HEIGHT 0x0810000A
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_STRIDE 0x0810000C
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_BYTE_STRIDE 0x0810000E
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_FORMAT 0x08100010
#define GRALLOC_MODULE_PERFORM_GET_HADNLE_SIZE 0x08100012
#define GRALLOC_MODULE_PERFORM_GET_USAGE 0x0feeff03
DrmGralloc::DrmGralloc(){
#if USE_GRALLOC_4
gralloc4::init_env_property();
#else
int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)&gralloc_);
if(ret)
ALOGE("hw_get_module fail");
#endif
}
DrmGralloc::~DrmGralloc(){
if(drmDeviceFd_>0)
close(drmDeviceFd_);
}
int DrmGralloc::importBuffer(buffer_handle_t rawHandle, buffer_handle_t* outHandle)
{
#if USE_GRALLOC_4
int err = gralloc4::importBuffer(rawHandle, outHandle);
if (err != android::OK)
{
ALOGE("Failed to import buffer, err : %d", err);
return -1;
}
return err;
#else
return -1;
#endif
}
int DrmGralloc::freeBuffer(buffer_handle_t handle)
{
#if USE_GRALLOC_4
int err = gralloc4::freeBuffer(handle);
if (err != android::OK)
{
ALOGE("Failed to get buffer width, err : %d", err);
return -1;
}
return err;
#else
return -1;
#endif
}
void DrmGralloc::set_drm_version(int drm_device, int version){
#if USE_GRALLOC_4
gralloc4::set_drm_version(version);
#endif
drmDeviceFd_ = drm_device;
drmVersion_ = version;
return;
}
int DrmGralloc::hwc_get_handle_width(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
uint64_t width;
int err = gralloc4::get_width(hnd, &width);
if (err != android::OK)
{
ALOGE("Failed to get buffer width, err : %d", err);
return -1;
}
return (int)width;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_WIDTH;
int width = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &width);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return width;
#endif
}
int DrmGralloc::hwc_get_handle_height(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
uint64_t height;
int err = gralloc4::get_height(hnd, &height);
if (err != android::OK)
{
ALOGE("Failed to get buffer height, err : %d", err);
return -1;
}
return (int)height;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_HEIGHT;
int height = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &height);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return height;
#endif
}
int DrmGralloc::hwc_get_handle_stride(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
int pixel_stride;
int err = gralloc4::get_pixel_stride(hnd, &pixel_stride);
if (err != android::OK)
{
ALOGE("Failed to get buffer pixel_stride, err : %d", err);
return -1;
}
return pixel_stride;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_STRIDE;
int stride = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &stride);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return stride;
#endif
}
int DrmGralloc::hwc_get_handle_height_stride(buffer_handle_t hnd){
#if USE_GRALLOC_4
uint64_t height_stride;
int err = gralloc4::get_height_stride(hnd, &height_stride);
if (err != android::OK)
{
ALOGE("Failed to get buffer pixel_stride, err : %d", err);
return -1;
}
return (int)height_stride;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_HEIGHT;
int height = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &height);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return height;
#endif
}
int DrmGralloc::hwc_get_handle_byte_stride_workround(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
int byte_stride;
int err = gralloc4::get_byte_stride_workround(hnd, &byte_stride);
if (err != android::OK)
{
ALOGE("Failed to get buffer byte_stride, err : %d", err);
return -1;
}
return byte_stride;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_BYTE_STRIDE;
int byte_stride = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &byte_stride);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return byte_stride;
#endif
}
int DrmGralloc::hwc_get_handle_byte_stride(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
int byte_stride;
int err = gralloc4::get_byte_stride(hnd, &byte_stride);
if (err != android::OK)
{
ALOGE("Failed to get buffer byte_stride, err : %d", err);
return -1;
}
return byte_stride;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_BYTE_STRIDE;
int byte_stride = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &byte_stride);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return byte_stride;
#endif
}
int DrmGralloc::hwc_get_handle_format(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
int format_requested;
int err = gralloc4::get_format_requested(hnd, &format_requested);
if (err != android::OK)
{
ALOGE("Failed to get buffer format_requested, err : %d", err);
return -1;
}
return format_requested;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_FORMAT;
int format = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &format);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return format;
#endif
}
uint64_t DrmGralloc::hwc_get_handle_usage(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
uint64_t usage;
int err = gralloc4::get_usage(hnd, &usage);
if (err != android::OK)
{
ALOGE("Failed to get buffer usage, err : %d", err);
return -1;
}
return usage;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_USAGE;
uint64_t usage = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &usage);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return (uint64_t)usage;
#endif
}
int DrmGralloc::hwc_get_handle_size(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
uint64_t allocation_size;
int err = gralloc4::get_allocation_size(hnd, &allocation_size);
if (err != android::OK)
{
ALOGE("Failed to get buffer allocation_size, err : %d", err);
return -1;
}
return (int)allocation_size;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_SIZE;
int size = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &size);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return size;
#endif
}
/*
@func hwc_get_handle_attributes:get attributes from handle.Before call this api,As far as now,
we need register the buffer first.May be the register is good for processer I think
@param hnd:
@param attrs: if size of attrs is small than 5,it will return EINVAL else
width = attrs[0]
height = attrs[1]
stride = attrs[2]
format = attrs[3]
size = attrs[4]
*/
int DrmGralloc::hwc_get_handle_attributes(buffer_handle_t hnd, std::vector<int> *attrs)
{
int ret = 0;
#if USE_GRALLOC_4
#else
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_ATTRIBUTES;
if (!hnd)
return -EINVAL;
if(gralloc_ && gralloc_->perform)
{
ret = gralloc_->perform(gralloc_, op, hnd, attrs);
}
else
{
ret = -EINVAL;
}
if(ret) {
ALOGE("hwc_get_handle_attributes fail %d for:%s hnd=%p",ret,strerror(ret),hnd);
}
#endif
return ret;
}
int DrmGralloc::hwc_get_handle_attibute(buffer_handle_t hnd, attribute_flag_t flag)
{
#if USE_GRALLOC_4
switch ( flag )
{
case ATT_WIDTH:
return hwc_get_handle_width(hnd);
case ATT_HEIGHT:
return hwc_get_handle_height(hnd);
case ATT_STRIDE:
return hwc_get_handle_stride(hnd);
case ATT_FORMAT:
return hwc_get_handle_format(hnd);
case ATT_HEIGHT_STRIDE:
return hwc_get_handle_height_stride(hnd);
case ATT_SIZE:
return hwc_get_handle_size(hnd);
case ATT_BYTE_STRIDE:
return hwc_get_handle_byte_stride(hnd);
case ATT_BYTE_STRIDE_WORKROUND:
return hwc_get_handle_byte_stride_workround(hnd);
default:
LOG_ALWAYS_FATAL("unexpected flag : %d", flag);
return -1;
}
#else // USE_GRALLOC_4
std::vector<int> attrs;
int ret=0;
if(!hnd)
{
ALOGE("%s handle is null",__FUNCTION__);
return -1;
}
ret = hwc_get_handle_attributes(hnd, &attrs);
if(ret < 0)
{
ALOGE("getHandleAttributes fail %d for:%s",ret,strerror(ret));
return ret;
}
else
{
return attrs.at(flag);
}
#endif
}
/*
@func getHandlePrimeFd:get prime_fd from handle.Before call this api,As far as now, we
need register the buffer first.May be the register is good for processer I think
@param hnd:
@return fd: prime_fd. and driver can call the dma_buf_get to get the buffer
*/
int DrmGralloc::hwc_get_handle_primefd(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
int share_fd;
int err = gralloc4::get_share_fd(hnd, &share_fd);
if (err != android::OK)
{
ALOGE("Failed to get buffer share_fd, err : %d", err);
return -1;
}
return (int)share_fd;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_PRIME_FD;
int fd = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &fd);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return fd;
#endif
}
int DrmGralloc::hwc_get_handle_name(buffer_handle_t hnd, std::string &name){
#if USE_GRALLOC_4
int err = gralloc4::get_name(hnd, name);
if (err != android::OK)
{
ALOGE("Failed to get buffer share_fd, err : %d", err);
return -1;
}
return (int)err;
#else // USE_GRALLOC_4
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_PRIME_FD;
int fd = -1;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &fd);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return fd;
#endif
}
int DrmGralloc::hwc_get_handle_buffer_id(buffer_handle_t hnd, uint64_t *buffer_id){
#if USE_GRALLOC_4
int err = gralloc4::get_buffer_id(hnd, buffer_id);
if (err != android::OK)
{
ALOGE("Failed to get buffer share_fd, err : %d", err);
return -1;
}
return (int)err;
#else // USE_GRALLOC_4
return -1;
#endif
}
uint32_t DrmGralloc::hwc_get_handle_phy_addr(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
return 0;
#else
int ret = 0;
int op = GRALLOC_MODULE_PERFORM_GET_HADNLE_PHY_ADDR;
uint32_t phy_addr = 0;
if(gralloc_ && gralloc_->perform)
ret = gralloc_->perform(gralloc_, op, hnd, &phy_addr);
else
ret = -EINVAL;
if(ret != 0)
{
ALOGE("%s:cann't get value from gralloc", __FUNCTION__);
}
return phy_addr;
#endif
}
uint64_t DrmGralloc::hwc_get_handle_format_modifier(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
uint64_t format_modifier = 0;
format_modifier = gralloc4::get_format_modifier(hnd);
return format_modifier;
#else // #if USE_GRALLOC_4
return 0;
#endif
}
uint32_t DrmGralloc::hwc_get_handle_fourcc_format(buffer_handle_t hnd)
{
#if USE_GRALLOC_4
uint32_t fourcc_format = 0;
fourcc_format = gralloc4::get_fourcc_format(hnd);
return fourcc_format;
#else // #if USE_GRALLOC_4
return 0;
#endif
}
void* DrmGralloc::hwc_get_handle_lock(buffer_handle_t hnd, int width, int height){
void* cpu_addr = NULL;
#if USE_GRALLOC_4
int ret = gralloc4::lock(hnd,GRALLOC_USAGE_SW_READ_MASK,0,0,width,height,(void **)&cpu_addr);
if(ret != 0)
{
ALOGE("%s: fail to lock buffer, ret : %d", __FUNCTION__, ret);
}
#else // #if USE_GRALLOC_4
if(gralloc_)
gralloc_->lock(gralloc_,
hnd,
GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK, //gr_handle->usage,
0,
0,
width,
height,
(void **)&cpu_addr);
#endif
return cpu_addr;
}
int DrmGralloc::hwc_get_handle_unlock(buffer_handle_t hnd){
int ret = 0;
#if USE_GRALLOC_4
gralloc4::unlock(hnd);
#else // USE_GRALLOC_4
ret = gralloc_->unlock(gralloc_, hnd);
#endif // USE_GRALLOC_4
return ret;
}
int DrmGralloc::hwc_get_gemhandle_from_fd(uint64_t buffer_fd,
uint64_t buffer_id,
uint32_t *out_gem_handle){
auto mapGemHandle = mapGemHandles_.find(buffer_id);
if(mapGemHandle == mapGemHandles_.end()){
HWC2_ALOGD_IF_VERBOSE("Call drmPrimeFDToHandle buf_fd=%" PRIu64 " buf_id=%" PRIx64, buffer_fd, buffer_id);
uint32_t gem_handle;
int ret = drmPrimeFDToHandle(drmDeviceFd_, buffer_fd, &gem_handle);
if (ret) {
HWC2_ALOGE("failed to import prime fd %" PRIu64 " ret=%d", buffer_fd, ret);
return ret;
}
auto ptrGemHandle = std::make_shared<GemHandle>(drmDeviceFd_,gem_handle);
auto res = mapGemHandles_.insert(std::pair<uint64_t, std::shared_ptr<GemHandle>>(buffer_id, ptrGemHandle));
if(res.second==false){
HWC2_ALOGE("mapGemHandles_ insert fail. maybe buffer_id %" PRIu64 " has existed", buffer_id);
return -1;
}
HWC2_ALOGD_IF_VERBOSE("Get GemHandle buf_fd=%" PRIu64 " buf_id=%" PRIx64 " GemHandle=%d", buffer_fd, buffer_id, gem_handle);
*out_gem_handle = gem_handle;
return 0;
}
HWC2_ALOGD_IF_VERBOSE("Cache GemHandle buf_fd=%" PRIu64 " buf_id=%" PRIx64 " GemHandle=%d", buffer_fd, buffer_id,mapGemHandle->second->GetGemHandle());
mapGemHandle->second->AddRefCnt();
*out_gem_handle = mapGemHandle->second->GetGemHandle();
return 0;
}
int DrmGralloc::hwc_free_gemhandle(uint64_t buffer_id){
auto mapGemHandle = mapGemHandles_.find(buffer_id);
if(mapGemHandle == mapGemHandles_.end()){
HWC2_ALOGI("Can't find buf_id=%" PRIx64 " GemHandle.", buffer_id);
return -1;
}
if(mapGemHandle->second->CanRelease()){
mapGemHandles_.erase(mapGemHandle);
HWC2_ALOGD_IF_VERBOSE("Release GemHandle buf_id=%" PRIx64 " success!", buffer_id);
return 0;
}
HWC2_ALOGD_IF_VERBOSE("Sub GemHandle RefCnt buf_id=%" PRIx64 " success!", buffer_id);
return 0;
}
}