diff options
Diffstat (limited to 'mediatek.c')
-rw-r--r-- | mediatek.c | 140 |
1 files changed, 111 insertions, 29 deletions
@@ -19,12 +19,23 @@ #include <mediatek_drm.h> // clang-format on +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" #define TILE_TYPE_LINEAR 0 +#if defined(MTK_MT8183) || defined(MTK_MT8186) +#define SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING +#endif + +// All platforms except MT8173 should USE_NV12_FOR_HW_VIDEO_DECODING. +#if defined(MTK_MT8183) || defined(MTK_MT8186) || defined(MTK_MT8192) || defined(MTK_MT8195) +#define USE_NV12_FOR_HW_VIDEO_DECODING +#else +#define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS +#endif + struct mediatek_private_map_data { void *cached_addr; void *gem_addr; @@ -35,14 +46,36 @@ static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMA DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888 }; -#ifdef MTK_MT8183 -static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_NV12, - DRM_FORMAT_YUYV, DRM_FORMAT_YVU420, - DRM_FORMAT_YVU420_ANDROID }; -#else -static const uint32_t texture_source_formats[] = { DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID, - DRM_FORMAT_NV12 }; +// clang-format off +static const uint32_t texture_source_formats[] = { +#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING + DRM_FORMAT_NV21, + DRM_FORMAT_YUYV, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_ABGR16161616F, #endif + DRM_FORMAT_NV12, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU420_ANDROID +}; + +static const uint32_t video_yuv_formats[] = { + DRM_FORMAT_NV21, + DRM_FORMAT_NV12, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU420_ANDROID +}; +// clang-format on + +static bool is_video_yuv_format(uint32_t format) +{ + size_t i; + for (i = 0; i < ARRAY_SIZE(video_yuv_formats); ++i) { + if (format == video_yuv_formats[i]) + return true; + } + return false; +} static int mediatek_init(struct driver *drv) { @@ -65,7 +98,7 @@ static int mediatek_init(struct driver *drv) metadata.modifier = DRM_FORMAT_MOD_LINEAR; drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_DECODER); drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, BO_USE_HW_VIDEO_DECODER); -#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195) +#ifdef USE_NV12_FOR_HW_VIDEO_DECODING // TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well. drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, BO_USE_HW_VIDEO_DECODER); #endif @@ -107,6 +140,12 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint size_t plane; uint32_t stride; struct drm_mtk_gem_create gem_create = { 0 }; + /* + * We identify the ChromeOS Camera App buffers via these two USE flags. Those buffers need + * the same alignment as the video hardware encoding. + */ + const bool is_camera_preview = + (bo->meta.use_flags & BO_USE_SCANOUT) && (bo->meta.use_flags & BO_USE_CAMERA_WRITE); if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) { errno = EINVAL; @@ -116,12 +155,19 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint /* * Since the ARM L1 cache line size is 64 bytes, align to that as a - * performance optimization. + * performance optimization, except for video buffers on certain platforms, + * these should only be accessed from the GPU and VCODEC subsystems (maybe + * also MDP), so it's better to align to macroblocks. */ stride = drv_stride_from_format(format, width, 0); +#ifdef DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS + const uint32_t alignment = is_video_yuv_format(format) ? 16 : 64; + stride = ALIGN(stride, alignment); +#else stride = ALIGN(stride, 64); +#endif - if (bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) { + if ((bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) || is_camera_preview) { uint32_t aligned_height = ALIGN(height, 32); uint32_t padding[DRV_MAX_PLANES] = { 0 }; @@ -133,7 +179,7 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint drv_bo_from_format_and_padding(bo, stride, aligned_height, format, padding); } else { -#ifdef MTK_MT8183 +#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING /* * JPEG Encoder Accelerator requires 16x16 alignment. We want the buffer * from camera can be put in JEA directly so align the height to 16 @@ -172,6 +218,7 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 int ret, prime_fd; struct drm_mtk_gem_map_off gem_map = { 0 }; struct mediatek_private_map_data *priv; + void *addr = NULL; gem_map.handle = bo->handles[0].u32; @@ -187,22 +234,38 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 return MAP_FAILED; } - void *addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, - gem_map.offset); + addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, + gem_map.offset); + if (addr == MAP_FAILED) + goto out_close_prime_fd; vma->length = bo->meta.total_size; priv = calloc(1, sizeof(*priv)); - priv->prime_fd = prime_fd; - vma->priv = priv; + if (!priv) + goto out_unmap_addr; if (bo->meta.use_flags & BO_USE_RENDERSCRIPT) { priv->cached_addr = calloc(1, bo->meta.total_size); + if (!priv->cached_addr) + goto out_free_priv; + priv->gem_addr = addr; addr = priv->cached_addr; } + priv->prime_fd = prime_fd; + vma->priv = priv; + return addr; + +out_free_priv: + free(priv); +out_unmap_addr: + munmap(addr, bo->meta.total_size); +out_close_prime_fd: + close(prime_fd); + return MAP_FAILED; } static int mediatek_bo_unmap(struct bo *bo, struct vma *vma) @@ -258,37 +321,56 @@ static int mediatek_bo_flush(struct bo *bo, struct mapping *mapping) return 0; } -static uint32_t mediatek_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags) +static void mediatek_resolve_format_and_use_flags(struct driver *drv, uint32_t format, + uint64_t use_flags, uint32_t *out_format, + uint64_t *out_use_flags) { + *out_format = format; + *out_use_flags = use_flags; switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: #ifdef MTK_MT8183 /* Only MT8183 Camera subsystem offers private reprocessing * capability. CAMERA_READ indicates the buffer is intended for * reprocessing and hence given the private format for MTK. */ - if (use_flags & BO_USE_CAMERA_READ) - return DRM_FORMAT_MTISP_SXYZW10; + if (use_flags & BO_USE_CAMERA_READ) { + *out_format = DRM_FORMAT_MTISP_SXYZW10; + break; + } #endif - if (use_flags & BO_USE_CAMERA_WRITE) - return DRM_FORMAT_NV12; + if (use_flags & BO_USE_CAMERA_WRITE) { + *out_format = DRM_FORMAT_NV12; + break; + } - /*HACK: See b/28671744 */ - return DRM_FORMAT_XBGR8888; + /* HACK: See b/28671744 */ + *out_format = DRM_FORMAT_XBGR8888; + *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + break; case DRM_FORMAT_FLEX_YCbCr_420_888: -#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195) +#ifdef USE_NV12_FOR_HW_VIDEO_DECODING // TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well. if (use_flags & (BO_USE_HW_VIDEO_DECODER)) { - return DRM_FORMAT_NV12; + *out_format = DRM_FORMAT_NV12; + break; } #endif if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) { - return DRM_FORMAT_NV12; + *out_format = DRM_FORMAT_NV12; + break; } - return DRM_FORMAT_YVU420; + + /* HACK: See b/139714614 */ + *out_format = DRM_FORMAT_YVU420; + *out_use_flags &= ~BO_USE_SCANOUT; + break; default: - return format; + break; } + /* Mediatek doesn't support YUV overlays */ + if (is_video_yuv_format(format)) + *out_use_flags &= ~BO_USE_SCANOUT; } const struct backend backend_mediatek = { @@ -302,7 +384,7 @@ const struct backend backend_mediatek = { .bo_unmap = mediatek_bo_unmap, .bo_invalidate = mediatek_bo_invalidate, .bo_flush = mediatek_bo_flush, - .resolve_format = mediatek_resolve_format, + .resolve_format_and_use_flags = mediatek_resolve_format_and_use_flags, }; #endif |