190 lines
6.0 KiB
C++
190 lines
6.0 KiB
C++
/*
|
|
* Copyright 2016 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "cros_gralloc_helpers.h"
|
|
|
|
#include <hardware/gralloc.h>
|
|
#include <sync/sync.h>
|
|
|
|
/* Define to match AIDL BufferUsage::VIDEO_DECODER. */
|
|
#define BUFFER_USAGE_VIDEO_DECODER (1 << 22)
|
|
|
|
/* Define to match AIDL BufferUsage::GPU_DATA_BUFFER. */
|
|
#define BUFFER_USAGE_GPU_DATA_BUFFER (1 << 24)
|
|
|
|
uint32_t cros_gralloc_convert_format(int format)
|
|
{
|
|
/*
|
|
* Conversion from HAL to fourcc-based DRV formats based on
|
|
* platform_android.c in mesa.
|
|
*/
|
|
|
|
switch (format) {
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
return DRM_FORMAT_ABGR8888;
|
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
return DRM_FORMAT_XBGR8888;
|
|
case HAL_PIXEL_FORMAT_RGB_888:
|
|
return DRM_FORMAT_BGR888;
|
|
/*
|
|
* Confusingly, HAL_PIXEL_FORMAT_RGB_565 is defined as:
|
|
*
|
|
* "16-bit packed format that has 5-bit R, 6-bit G, and 5-bit B components, in that
|
|
* order, from the most-sigfinicant bits to the least-significant bits."
|
|
*
|
|
* so the order of the components is intentionally not flipped between the pixel
|
|
* format and the DRM format.
|
|
*/
|
|
case HAL_PIXEL_FORMAT_RGB_565:
|
|
return DRM_FORMAT_RGB565;
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
return DRM_FORMAT_ARGB8888;
|
|
case HAL_PIXEL_FORMAT_RAW16:
|
|
return DRM_FORMAT_R16;
|
|
/*
|
|
* Choose DRM_FORMAT_R8 because <system/graphics.h> requires the buffers
|
|
* with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width
|
|
* equal to their size in bytes.
|
|
*/
|
|
case HAL_PIXEL_FORMAT_BLOB:
|
|
return DRM_FORMAT_R8;
|
|
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
|
|
return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED;
|
|
case HAL_PIXEL_FORMAT_YCbCr_420_888:
|
|
return DRM_FORMAT_FLEX_YCbCr_420_888;
|
|
case HAL_PIXEL_FORMAT_Y8:
|
|
return DRM_FORMAT_R8;
|
|
case HAL_PIXEL_FORMAT_Y16:
|
|
return DRM_FORMAT_R16;
|
|
case HAL_PIXEL_FORMAT_YV12:
|
|
return DRM_FORMAT_YVU420_ANDROID;
|
|
#if ANDROID_API_LEVEL >= 29
|
|
case HAL_PIXEL_FORMAT_RGBA_FP16:
|
|
return DRM_FORMAT_ABGR16161616F;
|
|
case HAL_PIXEL_FORMAT_RGBA_1010102:
|
|
return DRM_FORMAT_ABGR2101010;
|
|
#endif
|
|
#if ANDROID_API_LEVEL >= 30
|
|
case HAL_PIXEL_FORMAT_YCBCR_P010:
|
|
return DRM_FORMAT_P010;
|
|
#endif
|
|
}
|
|
|
|
return DRM_FORMAT_NONE;
|
|
}
|
|
|
|
static inline void handle_usage(uint64_t *gralloc_usage, uint64_t gralloc_mask,
|
|
uint64_t *bo_use_flags, uint64_t bo_mask)
|
|
{
|
|
if ((*gralloc_usage) & gralloc_mask) {
|
|
(*gralloc_usage) &= ~gralloc_mask;
|
|
(*bo_use_flags) |= bo_mask;
|
|
}
|
|
}
|
|
|
|
uint64_t cros_gralloc_convert_usage(uint64_t usage)
|
|
{
|
|
uint64_t use_flags = BO_USE_NONE;
|
|
|
|
/*
|
|
* GRALLOC_USAGE_SW_READ_OFTEN contains GRALLOC_USAGE_SW_READ_RARELY, thus OFTEN must be
|
|
* handled first. The same applies to GRALLOC_USAGE_SW_WRITE_OFTEN.
|
|
*/
|
|
handle_usage(&usage, GRALLOC_USAGE_SW_READ_OFTEN, &use_flags, BO_USE_SW_READ_OFTEN);
|
|
handle_usage(&usage, GRALLOC_USAGE_SW_READ_RARELY, &use_flags, BO_USE_SW_READ_RARELY);
|
|
handle_usage(&usage, GRALLOC_USAGE_SW_WRITE_OFTEN, &use_flags, BO_USE_SW_WRITE_OFTEN);
|
|
handle_usage(&usage, GRALLOC_USAGE_SW_WRITE_RARELY, &use_flags, BO_USE_SW_WRITE_RARELY);
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_TEXTURE, &use_flags, BO_USE_TEXTURE);
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_RENDER, &use_flags, BO_USE_RENDERING);
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_2D, &use_flags, BO_USE_RENDERING);
|
|
/* HWC wants to use display hardware, but can defer to OpenGL. */
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_COMPOSER, &use_flags,
|
|
BO_USE_SCANOUT | BO_USE_TEXTURE);
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_FB, &use_flags, BO_USE_NONE);
|
|
/*
|
|
* This flag potentially covers external display for the normal drivers (i915/rockchip) and
|
|
* usb monitors (evdi/udl). It's complicated so ignore it.
|
|
*/
|
|
handle_usage(&usage, GRALLOC_USAGE_EXTERNAL_DISP, &use_flags, BO_USE_NONE);
|
|
/* Map PROTECTED to linear until real HW protection is available on Android. */
|
|
handle_usage(&usage, GRALLOC_USAGE_PROTECTED, &use_flags, BO_USE_LINEAR);
|
|
handle_usage(&usage, GRALLOC_USAGE_CURSOR, &use_flags, BO_USE_NONE);
|
|
/* HACK: See b/30054495 for BO_USE_SW_READ_OFTEN. */
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_VIDEO_ENCODER, &use_flags,
|
|
BO_USE_HW_VIDEO_ENCODER | BO_USE_SW_READ_OFTEN);
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_CAMERA_WRITE, &use_flags, BO_USE_CAMERA_WRITE);
|
|
handle_usage(&usage, GRALLOC_USAGE_HW_CAMERA_READ, &use_flags, BO_USE_CAMERA_READ);
|
|
handle_usage(&usage, GRALLOC_USAGE_RENDERSCRIPT, &use_flags, BO_USE_RENDERSCRIPT);
|
|
handle_usage(&usage, BUFFER_USAGE_VIDEO_DECODER, &use_flags, BO_USE_HW_VIDEO_DECODER);
|
|
handle_usage(&usage, BUFFER_USAGE_GPU_DATA_BUFFER, &use_flags, BO_USE_GPU_DATA_BUFFER);
|
|
handle_usage(&usage, BUFFER_USAGE_FRONT_RENDERING, &use_flags, BO_USE_FRONT_RENDERING);
|
|
|
|
if (usage) {
|
|
drv_log("Unhandled gralloc usage: %llx\n", (unsigned long long)usage);
|
|
return BO_USE_NONE;
|
|
}
|
|
|
|
return use_flags;
|
|
}
|
|
|
|
uint32_t cros_gralloc_convert_map_usage(uint64_t usage)
|
|
{
|
|
uint32_t map_flags = BO_MAP_NONE;
|
|
|
|
if (usage & GRALLOC_USAGE_SW_READ_MASK)
|
|
map_flags |= BO_MAP_READ;
|
|
if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
|
|
map_flags |= BO_MAP_WRITE;
|
|
|
|
return map_flags;
|
|
}
|
|
|
|
cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle)
|
|
{
|
|
auto hnd = reinterpret_cast<cros_gralloc_handle_t>(handle);
|
|
if (!hnd || hnd->magic != cros_gralloc_magic)
|
|
return nullptr;
|
|
|
|
return hnd;
|
|
}
|
|
|
|
int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence)
|
|
{
|
|
if (fence < 0)
|
|
return 0;
|
|
|
|
/*
|
|
* Wait initially for 1000 ms, and then wait indefinitely. The SYNC_IOC_WAIT
|
|
* documentation states the caller waits indefinitely on the fence if timeout < 0.
|
|
*/
|
|
int err = sync_wait(fence, 1000);
|
|
if (err < 0) {
|
|
drv_log("Timed out on sync wait, err = %s\n", strerror(errno));
|
|
err = sync_wait(fence, -1);
|
|
if (err < 0) {
|
|
drv_log("sync wait error = %s\n", strerror(errno));
|
|
return -errno;
|
|
}
|
|
}
|
|
|
|
if (close_fence) {
|
|
err = close(fence);
|
|
if (err) {
|
|
drv_log("Unable to close fence fd, err = %s\n", strerror(errno));
|
|
return -errno;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
std::string get_drm_format_string(uint32_t drm_format)
|
|
{
|
|
char *sequence = (char *)&drm_format;
|
|
std::string s(sequence, 4);
|
|
return "DRM_FOURCC_" + s;
|
|
}
|