Merge remote-tracking branch 'aosp/upstream-main' into 'aosp/main' am: 21fc4f10c8 am: 2f8cb4cd96 am: 47a79c7f79
Original change: https://android-review.googlesource.com/c/platform/external/minigbm/+/2606528 Change-Id: I4f5979ff890f8e024f567678772cedcce2d7eed8 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
9a379409ec
19 changed files with 543 additions and 271 deletions
29
amdgpu.c
29
amdgpu.c
|
|
@ -518,14 +518,28 @@ static int amdgpu_create_bo_linear(struct bo *bo, uint32_t width, uint32_t heigh
|
|||
uint64_t use_flags)
|
||||
{
|
||||
int ret;
|
||||
bool need_align = false;
|
||||
uint32_t stride_align = 1;
|
||||
uint32_t plane, stride;
|
||||
uint32_t stride;
|
||||
union drm_amdgpu_gem_create gem_create = { { 0 } };
|
||||
struct amdgpu_priv *priv = bo->drv->priv;
|
||||
|
||||
stride = drv_stride_from_format(format, width, 0);
|
||||
|
||||
if (use_flags & BO_USE_HW_MASK) {
|
||||
/* some clients (e.g., virtio-wl) set BO_USE_LINEAR to mean
|
||||
* BO_USE_SCANOUT or BO_USE_TEXTURE
|
||||
*/
|
||||
need_align = use_flags & (BO_USE_HW_MASK | BO_USE_LINEAR);
|
||||
|
||||
#if defined(ANDROID) && ANDROID_API_LEVEL < 30
|
||||
/* work around
|
||||
* android.hardware.camera2.cts.ImageWriterTest#testYuvImageWriterReaderOperation
|
||||
* failure before R
|
||||
*/
|
||||
need_align = true;
|
||||
#endif
|
||||
|
||||
if (need_align) {
|
||||
/* GFX9+ requires the stride to be aligned to 256 bytes */
|
||||
stride_align = 256;
|
||||
stride = ALIGN(stride, stride_align);
|
||||
|
|
@ -595,8 +609,7 @@ static int amdgpu_create_bo_linear(struct bo *bo, uint32_t width, uint32_t heigh
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = gem_create.out.handle;
|
||||
bo->handle.u32 = gem_create.out.handle;
|
||||
|
||||
bo->meta.format_modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
|
||||
|
|
@ -689,7 +702,7 @@ static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
union drm_amdgpu_gem_mmap gem_map = { { 0 } };
|
||||
struct drm_amdgpu_gem_create_in bo_info = { 0 };
|
||||
struct drm_amdgpu_gem_op gem_op = { 0 };
|
||||
uint32_t handle = bo->handles[0].u32;
|
||||
uint32_t handle = bo->handle.u32;
|
||||
struct amdgpu_linear_vma_priv *priv = NULL;
|
||||
struct amdgpu_priv *drv_priv;
|
||||
|
||||
|
|
@ -731,7 +744,7 @@ static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
priv->map_flags = map_flags;
|
||||
handle = priv->handle = gem_create.out.handle;
|
||||
|
||||
ret = sdma_copy(bo->drv->priv, bo->drv->fd, bo->handles[0].u32, priv->handle,
|
||||
ret = sdma_copy(bo->drv->priv, bo->drv->fd, bo->handle.u32, priv->handle,
|
||||
bo_info.bo_size);
|
||||
if (ret) {
|
||||
drv_loge("SDMA copy for read failed\n");
|
||||
|
|
@ -779,7 +792,7 @@ static int amdgpu_unmap_bo(struct bo *bo, struct vma *vma)
|
|||
|
||||
if (BO_MAP_WRITE & priv->map_flags) {
|
||||
r = sdma_copy(bo->drv->priv, bo->drv->fd, priv->handle,
|
||||
bo->handles[0].u32, vma->length);
|
||||
bo->handle.u32, vma->length);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
|
@ -800,7 +813,7 @@ static int amdgpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
|||
if (bo->priv)
|
||||
return 0;
|
||||
|
||||
wait_idle.in.handle = bo->handles[0].u32;
|
||||
wait_idle.in.handle = bo->handle.u32;
|
||||
wait_idle.in.timeout = AMDGPU_TIMEOUT_INFINITE;
|
||||
|
||||
ret = drmCommandWriteRead(bo->drv->fd, DRM_AMDGPU_GEM_WAIT_IDLE, &wait_idle,
|
||||
|
|
|
|||
|
|
@ -138,15 +138,6 @@ int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_fla
|
|||
|
||||
memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
|
||||
|
||||
/*
|
||||
* Gralloc consumers don't support more than one kernel buffer per buffer object yet, so
|
||||
* just use the first kernel buffer.
|
||||
*/
|
||||
if (drv_num_buffers_per_bo(bo_) != 1) {
|
||||
ALOGE("Can only support one buffer per bo.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (map_flags) {
|
||||
if (lock_data_[0]) {
|
||||
drv_bo_invalidate(bo_, lock_data_[0]);
|
||||
|
|
|
|||
|
|
@ -155,9 +155,6 @@ static void drv_destroy_and_close(struct driver *drv)
|
|||
|
||||
cros_gralloc_driver::cros_gralloc_driver() : drv_(init_try_nodes(), drv_destroy_and_close)
|
||||
{
|
||||
char buf[PROP_VALUE_MAX];
|
||||
property_get("ro.product.device", buf, "unknown");
|
||||
mt8183_camera_quirk_ = !strncmp(buf, "kukui", strlen("kukui"));
|
||||
}
|
||||
|
||||
cros_gralloc_driver::~cros_gralloc_driver()
|
||||
|
|
@ -179,14 +176,6 @@ bool cros_gralloc_driver::get_resolved_format_and_use_flags(
|
|||
uint64_t resolved_use_flags;
|
||||
struct combination *combo;
|
||||
|
||||
if (mt8183_camera_quirk_ && (descriptor->use_flags & BO_USE_CAMERA_READ) &&
|
||||
!(descriptor->use_flags & BO_USE_SCANOUT) &&
|
||||
descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED) {
|
||||
*out_use_flags = descriptor->use_flags;
|
||||
*out_format = DRM_FORMAT_MTISP_SXYZW10;
|
||||
return true;
|
||||
}
|
||||
|
||||
drv_resolve_format_and_use_flags(drv_.get(), descriptor->drm_format, descriptor->use_flags,
|
||||
&resolved_format, &resolved_use_flags);
|
||||
|
||||
|
|
@ -273,16 +262,6 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto
|
|||
return -errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a desire for more than one kernel buffer, this can be
|
||||
* removed once the ArcCodec and Wayland service have the ability to
|
||||
* send more than one fd. GL/Vulkan drivers may also have to modified.
|
||||
*/
|
||||
if (drv_num_buffers_per_bo(bo) != 1) {
|
||||
ALOGE("Can only support one buffer per bo.");
|
||||
goto destroy_bo;
|
||||
}
|
||||
|
||||
num_planes = drv_bo_get_num_planes(bo);
|
||||
num_fds = num_planes;
|
||||
|
||||
|
|
@ -359,7 +338,6 @@ destroy_hnd:
|
|||
native_handle_close(hnd);
|
||||
native_handle_delete(hnd);
|
||||
|
||||
destroy_bo:
|
||||
drv_bo_destroy(bo);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ class cros_gralloc_driver
|
|||
std::mutex mutex_;
|
||||
std::unordered_map<uint32_t, std::unique_ptr<cros_gralloc_buffer>> buffers_;
|
||||
std::unordered_map<cros_gralloc_handle_t, cros_gralloc_imported_handle_info> handles_;
|
||||
bool mt8183_camera_quirk_ = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -153,10 +153,19 @@ uint32_t cros_gralloc_convert_map_usage(uint64_t usage)
|
|||
|
||||
cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle)
|
||||
{
|
||||
if (sizeof(native_handle_t) + (sizeof(int) * (handle->numFds + handle->numInts)) !=
|
||||
sizeof(struct cros_gralloc_handle))
|
||||
return nullptr;
|
||||
|
||||
auto hnd = reinterpret_cast<cros_gralloc_handle_t>(handle);
|
||||
if (!hnd || hnd->magic != cros_gralloc_magic)
|
||||
return nullptr;
|
||||
|
||||
// if hnd->reserved_region_size == 0, handle->numFds is hnd->num_planes
|
||||
// if hnd->reserved_region_size > 0, handle->numFds is hnd->num_planes + 1
|
||||
if ((uint32_t)handle->numFds != hnd->num_planes + (hnd->reserved_region_size > 0))
|
||||
return nullptr;
|
||||
|
||||
return hnd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,11 @@ static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle)
|
|||
int32_t ret;
|
||||
auto mod = (struct gralloc0_module const *)dev->common.module;
|
||||
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mod->driver->release(handle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -173,6 +178,11 @@ static int gralloc0_open(const struct hw_module_t *mod, const char *name, struct
|
|||
|
||||
static int gralloc0_register_buffer(struct gralloc_module_t const *module, buffer_handle_t handle)
|
||||
{
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
auto const_module = reinterpret_cast<const struct gralloc0_module *>(module);
|
||||
auto mod = const_cast<struct gralloc0_module *>(const_module);
|
||||
|
||||
|
|
@ -186,6 +196,11 @@ static int gralloc0_register_buffer(struct gralloc_module_t const *module, buffe
|
|||
|
||||
static int gralloc0_unregister_buffer(struct gralloc_module_t const *module, buffer_handle_t handle)
|
||||
{
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
auto mod = (struct gralloc0_module const *)module;
|
||||
return mod->driver->release(handle);
|
||||
}
|
||||
|
|
@ -193,12 +208,23 @@ static int gralloc0_unregister_buffer(struct gralloc_module_t const *module, buf
|
|||
static int gralloc0_lock(struct gralloc_module_t const *module, buffer_handle_t handle, int usage,
|
||||
int l, int t, int w, int h, void **vaddr)
|
||||
{
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return module->lockAsync(module, handle, usage, l, t, w, h, vaddr, -1);
|
||||
}
|
||||
|
||||
static int gralloc0_unlock(struct gralloc_module_t const *module, buffer_handle_t handle)
|
||||
{
|
||||
int32_t fence_fd, ret;
|
||||
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
auto mod = (struct gralloc0_module const *)module;
|
||||
ret = mod->driver->unlock(handle, &fence_fd);
|
||||
if (ret)
|
||||
|
|
@ -244,6 +270,10 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...)
|
|||
case GRALLOC_DRM_GET_BUFFER_INFO:
|
||||
/* retrieve handles for ops with buffer_handle_t */
|
||||
handle = va_arg(args, buffer_handle_t);
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
hnd = cros_gralloc_convert_handle(handle);
|
||||
if (!hnd) {
|
||||
va_end(args);
|
||||
|
|
@ -349,6 +379,11 @@ static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_han
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
auto hnd = cros_gralloc_convert_handle(handle);
|
||||
if (!hnd) {
|
||||
ALOGE("Invalid handle.");
|
||||
|
|
@ -375,6 +410,12 @@ static int gralloc0_unlock_async(struct gralloc_module_t const *module, buffer_h
|
|||
int *fence_fd)
|
||||
{
|
||||
auto mod = (struct gralloc0_module const *)module;
|
||||
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mod->driver->unlock(handle, fence_fd);
|
||||
}
|
||||
|
||||
|
|
@ -400,6 +441,11 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
ALOGE("Invalid buffer handle.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
auto hnd = cros_gralloc_convert_handle(handle);
|
||||
if (!hnd) {
|
||||
ALOGE("Invalid handle.");
|
||||
|
|
|
|||
107
dri.c
107
dri.c
|
|
@ -67,29 +67,15 @@ static bool lookup_extension(const __DRIextension *const *extensions, const char
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close Gem Handle
|
||||
*/
|
||||
static void close_gem_handle(uint32_t handle, int fd)
|
||||
{
|
||||
struct drm_gem_close gem_close = { 0 };
|
||||
int ret = 0;
|
||||
|
||||
gem_close.handle = handle;
|
||||
ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
if (ret)
|
||||
drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", handle, ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* The DRI GEM namespace may be different from the minigbm's driver GEM namespace. We have
|
||||
* to import into minigbm.
|
||||
*/
|
||||
static int import_into_minigbm(struct dri_driver *dri, struct bo *bo)
|
||||
{
|
||||
uint32_t handle;
|
||||
int ret, modifier_upper, modifier_lower, num_planes, i, j;
|
||||
off_t dmabuf_sizes[DRV_MAX_PLANES];
|
||||
uint32_t handle = 0;
|
||||
int ret, modifier_upper, modifier_lower, num_planes, prime_fd;
|
||||
off_t dmabuf_size;
|
||||
__DRIimage *plane_image = NULL;
|
||||
|
||||
if (dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
|
||||
|
|
@ -105,8 +91,30 @@ static int import_into_minigbm(struct dri_driver *dri, struct bo *bo)
|
|||
return -errno;
|
||||
|
||||
bo->meta.num_planes = num_planes;
|
||||
for (i = 0; i < num_planes; ++i) {
|
||||
int prime_fd, stride, offset;
|
||||
|
||||
if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_FD, &prime_fd))
|
||||
return -errno;
|
||||
|
||||
dmabuf_size = lseek(prime_fd, 0, SEEK_END);
|
||||
if (dmabuf_size == (off_t)-1) {
|
||||
close(prime_fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
lseek(prime_fd, 0, SEEK_SET);
|
||||
|
||||
ret = drmPrimeFDToHandle(bo->drv->fd, prime_fd, &handle);
|
||||
|
||||
close(prime_fd);
|
||||
|
||||
if (ret) {
|
||||
drv_loge("drmPrimeFDToHandle failed with %s\n", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bo->handle.u32 = handle;
|
||||
for (int i = 0; i < num_planes; ++i) {
|
||||
int stride, offset;
|
||||
plane_image = dri->image_extension->fromPlanar(bo->priv, i, NULL);
|
||||
__DRIimage *image = plane_image ? plane_image : bo->priv;
|
||||
|
||||
|
|
@ -116,73 +124,28 @@ static int import_into_minigbm(struct dri_driver *dri, struct bo *bo)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &prime_fd)) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dmabuf_sizes[i] = lseek(prime_fd, 0, SEEK_END);
|
||||
if (dmabuf_sizes[i] == (off_t)-1) {
|
||||
ret = -errno;
|
||||
close(prime_fd);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
lseek(prime_fd, 0, SEEK_SET);
|
||||
|
||||
ret = drmPrimeFDToHandle(bo->drv->fd, prime_fd, &handle);
|
||||
|
||||
close(prime_fd);
|
||||
|
||||
if (ret) {
|
||||
drv_loge("drmPrimeFDToHandle failed with %s\n", strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
bo->handles[i].u32 = handle;
|
||||
|
||||
bo->meta.strides[i] = stride;
|
||||
bo->meta.offsets[i] = offset;
|
||||
|
||||
if (plane_image)
|
||||
dri->image_extension->destroyImage(plane_image);
|
||||
|
||||
if (i > 0)
|
||||
bo->meta.sizes[i - 1] = bo->meta.offsets[i] - bo->meta.offsets[i - 1];
|
||||
}
|
||||
|
||||
for (i = 0; i < num_planes; ++i) {
|
||||
off_t next_plane = dmabuf_sizes[i];
|
||||
for (j = 0; j < num_planes; ++j) {
|
||||
if (bo->meta.offsets[j] < next_plane &&
|
||||
bo->meta.offsets[j] > bo->meta.offsets[i] &&
|
||||
bo->handles[j].u32 == bo->handles[i].u32)
|
||||
next_plane = bo->meta.offsets[j];
|
||||
}
|
||||
|
||||
bo->meta.sizes[i] = next_plane - bo->meta.offsets[i];
|
||||
|
||||
/* This is kind of misleading if different planes use
|
||||
different dmabufs. */
|
||||
bo->meta.total_size += bo->meta.sizes[i];
|
||||
}
|
||||
bo->meta.sizes[num_planes - 1] = dmabuf_size - bo->meta.offsets[num_planes - 1];
|
||||
bo->meta.total_size = dmabuf_size;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
if (plane_image)
|
||||
dri->image_extension->destroyImage(plane_image);
|
||||
while (--i >= 0) {
|
||||
for (j = 0; j <= i; ++j)
|
||||
if (bo->handles[j].u32 == bo->handles[i].u32)
|
||||
break;
|
||||
|
||||
/* Multiple equivalent handles) */
|
||||
if (i == j)
|
||||
break;
|
||||
if (handle != 0)
|
||||
drv_gem_close(bo->drv, handle);
|
||||
|
||||
/* This kind of goes horribly wrong when we already imported
|
||||
* the same handles earlier, as we should really reference
|
||||
* count handles. */
|
||||
close_gem_handle(bo->handles[i].u32, bo->drv->fd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -416,7 +379,7 @@ int dri_bo_release(struct bo *bo)
|
|||
int dri_bo_destroy(struct bo *bo)
|
||||
{
|
||||
assert(bo->priv);
|
||||
close_gem_handle(bo->handles[0].u32, bo->drv->fd);
|
||||
drv_gem_close(bo->drv, bo->handle.u32);
|
||||
bo->priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
57
drv.c
57
drv.c
|
|
@ -18,6 +18,9 @@
|
|||
#ifdef __ANDROID__
|
||||
#include <cutils/log.h>
|
||||
#include <libgen.h>
|
||||
#define MINIGBM_DEBUG "vendor.minigbm.debug"
|
||||
#else
|
||||
#define MINIGBM_DEBUG "MINIGBM_DEBUG"
|
||||
#endif
|
||||
|
||||
#include "drv_helpers.h"
|
||||
|
|
@ -113,8 +116,8 @@ struct driver *drv_create(int fd)
|
|||
if (!drv)
|
||||
return NULL;
|
||||
|
||||
char *minigbm_debug;
|
||||
minigbm_debug = getenv("MINIGBM_DEBUG");
|
||||
const char *minigbm_debug;
|
||||
minigbm_debug = drv_get_os_option(MINIGBM_DEBUG);
|
||||
drv->compression = (minigbm_debug == NULL) || (strcmp(minigbm_debug, "nocompression") != 0);
|
||||
|
||||
drv->fd = fd;
|
||||
|
|
@ -250,7 +253,7 @@ static void drv_bo_mapping_destroy(struct bo *bo)
|
|||
while (idx < drv_array_size(drv->mappings)) {
|
||||
struct mapping *mapping =
|
||||
(struct mapping *)drv_array_at_idx(drv->mappings, idx);
|
||||
if (mapping->vma->handle != bo->handles[plane].u32) {
|
||||
if (mapping->vma->handle != bo->handle.u32) {
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -285,10 +288,10 @@ static void drv_bo_acquire(struct bo *bo)
|
|||
for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
|
||||
uintptr_t num = 0;
|
||||
|
||||
if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num))
|
||||
drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
|
||||
if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num))
|
||||
drmHashDelete(drv->buffer_table, bo->handle.u32);
|
||||
|
||||
drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num + 1));
|
||||
drmHashInsert(drv->buffer_table, bo->handle.u32, (void *)(num + 1));
|
||||
}
|
||||
pthread_mutex_unlock(&drv->buffer_table_lock);
|
||||
}
|
||||
|
|
@ -307,19 +310,18 @@ static bool drv_bo_release(struct bo *bo)
|
|||
|
||||
pthread_mutex_lock(&drv->buffer_table_lock);
|
||||
for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
|
||||
if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num)) {
|
||||
drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
|
||||
if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num)) {
|
||||
drmHashDelete(drv->buffer_table, bo->handle.u32);
|
||||
|
||||
if (num > 1) {
|
||||
drmHashInsert(drv->buffer_table, bo->handles[plane].u32,
|
||||
(void *)(num - 1));
|
||||
drmHashInsert(drv->buffer_table, bo->handle.u32, (void *)(num - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The same buffer can back multiple planes with different offsets. */
|
||||
for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
|
||||
if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num)) {
|
||||
if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num)) {
|
||||
/* num is positive if found in the hashmap. */
|
||||
pthread_mutex_unlock(&drv->buffer_table_lock);
|
||||
return false;
|
||||
|
|
@ -491,8 +493,7 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags
|
|||
|
||||
for (i = 0; i < drv_array_size(drv->mappings); i++) {
|
||||
struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
|
||||
if (prior->vma->handle != bo->handles[plane].u32 ||
|
||||
prior->vma->map_flags != map_flags)
|
||||
if (prior->vma->handle != bo->handle.u32 || prior->vma->map_flags != map_flags)
|
||||
continue;
|
||||
|
||||
if (rect->x != prior->rect.x || rect->y != prior->rect.y ||
|
||||
|
|
@ -506,8 +507,7 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags
|
|||
|
||||
for (i = 0; i < drv_array_size(drv->mappings); i++) {
|
||||
struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
|
||||
if (prior->vma->handle != bo->handles[plane].u32 ||
|
||||
prior->vma->map_flags != map_flags)
|
||||
if (prior->vma->handle != bo->handle.u32 || prior->vma->map_flags != map_flags)
|
||||
continue;
|
||||
|
||||
prior->vma->refcount++;
|
||||
|
|
@ -533,7 +533,7 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags
|
|||
|
||||
mapping.vma->refcount = 1;
|
||||
mapping.vma->addr = addr;
|
||||
mapping.vma->handle = bo->handles[plane].u32;
|
||||
mapping.vma->handle = bo->handle.u32;
|
||||
mapping.vma->map_flags = map_flags;
|
||||
|
||||
success:
|
||||
|
|
@ -639,7 +639,7 @@ size_t drv_bo_get_num_planes(struct bo *bo)
|
|||
|
||||
union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane)
|
||||
{
|
||||
return bo->handles[plane];
|
||||
return bo->handle;
|
||||
}
|
||||
|
||||
#ifndef DRM_RDWR
|
||||
|
|
@ -655,11 +655,11 @@ int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
|
|||
if (bo->is_test_buffer)
|
||||
return -EINVAL;
|
||||
|
||||
ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
|
||||
ret = drmPrimeHandleToFD(bo->drv->fd, bo->handle.u32, DRM_CLOEXEC | DRM_RDWR, &fd);
|
||||
|
||||
// Older DRM implementations blocked DRM_RDWR, but gave a read/write mapping anyways
|
||||
if (ret)
|
||||
ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC, &fd);
|
||||
ret = drmPrimeHandleToFD(bo->drv->fd, bo->handle.u32, DRM_CLOEXEC, &fd);
|
||||
|
||||
if (ret)
|
||||
drv_loge("Failed to get plane fd: %s\n", strerror(errno));
|
||||
|
|
@ -727,25 +727,6 @@ void drv_resolve_format_and_use_flags(struct driver *drv, uint32_t format, uint6
|
|||
out_use_flags);
|
||||
}
|
||||
|
||||
uint32_t drv_num_buffers_per_bo(struct bo *bo)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
size_t plane, p;
|
||||
|
||||
if (bo->is_test_buffer)
|
||||
return 0;
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++) {
|
||||
for (p = 0; p < plane; p++)
|
||||
if (bo->handles[p].u32 == bo->handles[plane].u32)
|
||||
break;
|
||||
if (p == plane)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void drv_log_prefix(enum drv_log_level level, const char *prefix, const char *file, int line,
|
||||
const char *format, ...)
|
||||
{
|
||||
|
|
|
|||
7
drv.h
7
drv.h
|
|
@ -207,9 +207,6 @@ uint64_t drv_resolve_use_flags(struct driver *drv, uint32_t format, uint64_t use
|
|||
size_t drv_num_planes_from_format(uint32_t format);
|
||||
|
||||
size_t drv_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier);
|
||||
|
||||
uint32_t drv_num_buffers_per_bo(struct bo *bo);
|
||||
|
||||
int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
|
||||
uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier);
|
||||
|
||||
|
|
@ -228,7 +225,11 @@ enum drv_log_level {
|
|||
} while (0)
|
||||
|
||||
#define drv_loge(format, ...) _drv_log(DRV_LOGE, format, ##__VA_ARGS__)
|
||||
#ifdef NDEBUG
|
||||
#define drv_logv(format, ...)
|
||||
#else
|
||||
#define drv_logv(format, ...) _drv_log(DRV_LOGV, format, ##__VA_ARGS__)
|
||||
#endif
|
||||
#define drv_logd(format, ...) _drv_log(DRV_LOGD, format, ##__VA_ARGS__)
|
||||
#define drv_logi(format, ...) _drv_log(DRV_LOGI, format, ##__VA_ARGS__)
|
||||
|
||||
|
|
|
|||
126
drv_helpers.c
126
drv_helpers.c
|
|
@ -16,6 +16,10 @@
|
|||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <cutils/properties.h>
|
||||
#endif
|
||||
|
||||
#include "drv_priv.h"
|
||||
#include "util.h"
|
||||
|
||||
|
|
@ -329,7 +333,6 @@ int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32
|
|||
uint64_t use_flags, uint64_t quirks)
|
||||
{
|
||||
int ret;
|
||||
size_t plane;
|
||||
uint32_t aligned_width, aligned_height;
|
||||
struct drm_mode_create_dumb create_dumb = { 0 };
|
||||
|
||||
|
|
@ -387,8 +390,7 @@ int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32
|
|||
|
||||
drv_bo_from_format(bo, create_dumb.pitch, 1, height, format);
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = create_dumb.handle;
|
||||
bo->handle.u32 = create_dumb.handle;
|
||||
|
||||
bo->meta.total_size = create_dumb.size;
|
||||
return 0;
|
||||
|
|
@ -405,44 +407,38 @@ int drv_dumb_bo_destroy(struct bo *bo)
|
|||
int ret;
|
||||
struct drm_mode_destroy_dumb destroy_dumb = { 0 };
|
||||
|
||||
destroy_dumb.handle = bo->handles[0].u32;
|
||||
destroy_dumb.handle = bo->handle.u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", bo->handles[0].u32);
|
||||
drv_loge("DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", bo->handle.u32);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_gem_bo_destroy(struct bo *bo)
|
||||
int drv_gem_close(struct driver *drv, uint32_t gem_handle)
|
||||
{
|
||||
struct drm_gem_close gem_close;
|
||||
int ret, error = 0;
|
||||
size_t plane, i;
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++) {
|
||||
for (i = 0; i < plane; i++)
|
||||
if (bo->handles[i].u32 == bo->handles[plane].u32)
|
||||
break;
|
||||
/* Make sure close hasn't already been called on this handle */
|
||||
if (i != plane)
|
||||
continue;
|
||||
memset(&gem_close, 0, sizeof(gem_close));
|
||||
gem_close.handle = gem_handle;
|
||||
|
||||
memset(&gem_close, 0, sizeof(gem_close));
|
||||
gem_close.handle = bo->handles[plane].u32;
|
||||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
|
||||
bo->handles[plane].u32, ret);
|
||||
error = -errno;
|
||||
}
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", gem_handle, ret);
|
||||
error = -errno;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int drv_gem_bo_destroy(struct bo *bo)
|
||||
{
|
||||
return drv_gem_close(bo->drv, bo->handle.u32);
|
||||
}
|
||||
|
||||
int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -455,21 +451,20 @@ int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data)
|
|||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle);
|
||||
|
||||
if (plane > 0 && !ret && bo->handle.u32 != prime_handle.handle) {
|
||||
drv_gem_close(bo->drv, prime_handle.handle);
|
||||
ret = -1;
|
||||
errno = EINVAL;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n", prime_handle.fd);
|
||||
|
||||
/*
|
||||
* Need to call GEM close on planes that were opened,
|
||||
* if any. Adjust the num_planes variable to be the
|
||||
* plane that failed, so GEM close will be called on
|
||||
* planes before that plane.
|
||||
*/
|
||||
bo->meta.num_planes = plane;
|
||||
drv_gem_bo_destroy(bo);
|
||||
if (plane > 0)
|
||||
drv_gem_close(bo->drv, bo->handle.u32);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
bo->handles[plane].u32 = prime_handle.handle;
|
||||
bo->handle.u32 = prime_handle.handle;
|
||||
}
|
||||
bo->meta.tiling = data->tiling;
|
||||
|
||||
|
|
@ -483,7 +478,7 @@ void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
struct drm_mode_map_dumb map_dumb;
|
||||
|
||||
memset(&map_dumb, 0, sizeof(map_dumb));
|
||||
map_dumb.handle = bo->handles[0].u32;
|
||||
map_dumb.handle = bo->handle.u32;
|
||||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
|
||||
if (ret) {
|
||||
|
|
@ -620,3 +615,66 @@ void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *drv_get_os_option(const char *name)
|
||||
{
|
||||
const char *ret = getenv(name);
|
||||
#ifdef __ANDROID__
|
||||
if (!ret) {
|
||||
static char prop[PROPERTY_VALUE_MAX];
|
||||
return property_get(name, prop, NULL) > 1 ? prop : NULL;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lru_remove_entry(struct lru_entry *entry)
|
||||
{
|
||||
entry->prev->next = entry->next;
|
||||
entry->next->prev = entry->prev;
|
||||
}
|
||||
|
||||
static void lru_link_entry(struct lru *lru, struct lru_entry *entry)
|
||||
{
|
||||
struct lru_entry *head = &lru->head;
|
||||
entry->prev = head;
|
||||
entry->next = head->next;
|
||||
|
||||
head->next->prev = entry;
|
||||
head->next = entry;
|
||||
}
|
||||
|
||||
struct lru_entry *lru_find(struct lru *lru, bool (*eq)(struct lru_entry *e, void *data), void *data)
|
||||
{
|
||||
struct lru_entry *head = &lru->head;
|
||||
struct lru_entry *cur = head->next;
|
||||
|
||||
while (cur != head) {
|
||||
if (eq(cur, data)) {
|
||||
lru_remove_entry(cur);
|
||||
lru_link_entry(lru, cur);
|
||||
return cur;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lru_insert(struct lru *lru, struct lru_entry *entry)
|
||||
{
|
||||
if (lru->count == lru->max) {
|
||||
lru_remove_entry(lru->head.prev);
|
||||
} else {
|
||||
lru->count++;
|
||||
}
|
||||
lru_link_entry(lru, entry);
|
||||
}
|
||||
|
||||
void lru_init(struct lru *lru, int max)
|
||||
{
|
||||
lru->head.next = &lru->head;
|
||||
lru->head.prev = &lru->head;
|
||||
lru->count = 0;
|
||||
lru->max = max;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t
|
|||
int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
|
||||
uint64_t use_flags, uint64_t quirks);
|
||||
int drv_dumb_bo_destroy(struct bo *bo);
|
||||
int drv_gem_close(struct driver *drv, uint32_t gem_handle);
|
||||
int drv_gem_bo_destroy(struct bo *bo);
|
||||
int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data);
|
||||
void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags);
|
||||
|
|
@ -50,4 +51,25 @@ void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format
|
|||
uint64_t use_flags, uint32_t *out_format,
|
||||
uint64_t *out_use_flags);
|
||||
|
||||
/*
|
||||
* Get an option. Should return NULL if specified option is not set.
|
||||
*/
|
||||
const char *drv_get_os_option(const char *name);
|
||||
|
||||
struct lru_entry {
|
||||
struct lru_entry *next;
|
||||
struct lru_entry *prev;
|
||||
};
|
||||
|
||||
struct lru {
|
||||
struct lru_entry head;
|
||||
int count;
|
||||
int max;
|
||||
};
|
||||
|
||||
struct lru_entry *lru_find(struct lru *lru, bool (*eq)(struct lru_entry *e, void *data),
|
||||
void *data);
|
||||
void lru_insert(struct lru *lru, struct lru_entry *entry);
|
||||
void lru_init(struct lru *lru, int max);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ struct bo {
|
|||
struct driver *drv;
|
||||
struct bo_metadata meta;
|
||||
bool is_test_buffer;
|
||||
union bo_handle handles[DRV_MAX_PLANES];
|
||||
union bo_handle handle;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
|
|
|||
28
i915.c
28
i915.c
|
|
@ -246,6 +246,9 @@ static int i915_add_combinations(struct driver *drv)
|
|||
BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER |
|
||||
hw_protected);
|
||||
|
||||
/* P010 linear can be used for scanout too. */
|
||||
drv_modify_combination(drv, DRM_FORMAT_P010, &metadata_linear, BO_USE_SCANOUT);
|
||||
|
||||
/* Android CTS tests require this. */
|
||||
drv_add_combination(drv, DRM_FORMAT_BGR888, &metadata_linear, BO_USE_SW_MASK);
|
||||
|
||||
|
|
@ -290,7 +293,7 @@ static int i915_add_combinations(struct driver *drv)
|
|||
&metadata_4_tiled, render_not_linear);
|
||||
drv_add_combinations(drv, scanout_render_formats,
|
||||
ARRAY_SIZE(scanout_render_formats), &metadata_4_tiled,
|
||||
render_not_linear);
|
||||
scanout_and_render_not_linear);
|
||||
} else {
|
||||
struct format_metadata metadata_y_tiled = { .tiling = I915_TILING_Y,
|
||||
.priority = 3,
|
||||
|
|
@ -406,9 +409,14 @@ static void i915_clflush(void *start, size_t size)
|
|||
|
||||
__builtin_ia32_mfence();
|
||||
while (p < end) {
|
||||
#if defined(__CLFLUSHOPT__)
|
||||
__builtin_ia32_clflushopt(p);
|
||||
#else
|
||||
__builtin_ia32_clflush(p);
|
||||
#endif
|
||||
p = (void *)((uintptr_t)p + I915_CACHELINE_SIZE);
|
||||
}
|
||||
__builtin_ia32_mfence();
|
||||
}
|
||||
|
||||
static int i915_init(struct driver *drv)
|
||||
|
|
@ -716,7 +724,6 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig
|
|||
static int i915_bo_create_from_metadata(struct bo *bo)
|
||||
{
|
||||
int ret;
|
||||
size_t plane;
|
||||
uint32_t gem_handle;
|
||||
struct drm_i915_gem_set_tiling gem_set_tiling = { 0 };
|
||||
struct i915_device *i915 = bo->drv->priv;
|
||||
|
|
@ -752,21 +759,20 @@ static int i915_bo_create_from_metadata(struct bo *bo)
|
|||
gem_handle = gem_create.handle;
|
||||
}
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = gem_handle;
|
||||
bo->handle.u32 = gem_handle;
|
||||
|
||||
/* Set/Get tiling ioctl not supported based on fence availability
|
||||
Refer : "https://patchwork.freedesktop.org/patch/325343/"
|
||||
*/
|
||||
if (i915->num_fences_avail) {
|
||||
gem_set_tiling.handle = bo->handles[0].u32;
|
||||
gem_set_tiling.handle = bo->handle.u32;
|
||||
gem_set_tiling.tiling_mode = bo->meta.tiling;
|
||||
gem_set_tiling.stride = bo->meta.strides[0];
|
||||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
|
||||
if (ret) {
|
||||
struct drm_gem_close gem_close = { 0 };
|
||||
gem_close.handle = bo->handles[0].u32;
|
||||
gem_close.handle = bo->handle.u32;
|
||||
drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
|
||||
drv_loge("DRM_IOCTL_I915_GEM_SET_TILING failed with %d\n", errno);
|
||||
|
|
@ -800,7 +806,7 @@ static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
|
|||
*/
|
||||
if (i915->num_fences_avail) {
|
||||
/* TODO(gsingh): export modifiers and get rid of backdoor tiling. */
|
||||
gem_get_tiling.handle = bo->handles[0].u32;
|
||||
gem_get_tiling.handle = bo->handle.u32;
|
||||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling);
|
||||
if (ret) {
|
||||
|
|
@ -827,7 +833,7 @@ static void *i915_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
if (bo->meta.tiling == I915_TILING_NONE) {
|
||||
if (i915->has_mmap_offset) {
|
||||
struct drm_i915_gem_mmap_offset gem_map = { 0 };
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
gem_map.handle = bo->handle.u32;
|
||||
gem_map.flags = I915_MMAP_OFFSET_WB;
|
||||
|
||||
/* Get the fake offset back */
|
||||
|
|
@ -850,7 +856,7 @@ static void *i915_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
(BO_USE_RENDERSCRIPT | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)))
|
||||
gem_map.flags = I915_MMAP_WC;
|
||||
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
gem_map.handle = bo->handle.u32;
|
||||
gem_map.offset = 0;
|
||||
gem_map.size = bo->meta.total_size;
|
||||
|
||||
|
|
@ -870,7 +876,7 @@ static void *i915_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
if (addr == MAP_FAILED) {
|
||||
struct drm_i915_gem_mmap_gtt gem_map = { 0 };
|
||||
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
gem_map.handle = bo->handle.u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_I915_GEM_MMAP_GTT failed\n");
|
||||
|
|
@ -895,7 +901,7 @@ static int i915_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
|||
int ret;
|
||||
struct drm_i915_gem_set_domain set_domain = { 0 };
|
||||
|
||||
set_domain.handle = bo->handles[0].u32;
|
||||
set_domain.handle = bo->handle.u32;
|
||||
if (bo->meta.tiling == I915_TILING_NONE) {
|
||||
set_domain.read_domains = I915_GEM_DOMAIN_CPU;
|
||||
if (mapping->vma->map_flags & BO_MAP_WRITE)
|
||||
|
|
|
|||
76
mediatek.c
76
mediatek.c
|
|
@ -29,10 +29,11 @@
|
|||
#if defined(MTK_MT8183) || \
|
||||
defined(MTK_MT8186)
|
||||
// clang-format on
|
||||
#define SUPPORTS_YUV422
|
||||
#define SUPPORT_YUV422
|
||||
#endif
|
||||
|
||||
// All platforms except MT8173 should USE_NV12_FOR_HW_VIDEO_DECODING.
|
||||
// All platforms except MT8173 should USE_NV12_FOR_HW_VIDEO_DECODING
|
||||
// and SUPPORT_FP16_AND_10BIT_ABGR
|
||||
// clang-format off
|
||||
#if defined(MTK_MT8183) || \
|
||||
defined(MTK_MT8186) || \
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
defined(MTK_MT8195)
|
||||
// clang-format on
|
||||
#define USE_NV12_FOR_HW_VIDEO_DECODING
|
||||
#define SUPPORT_FP16_AND_10BIT_ABGR
|
||||
#else
|
||||
#define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
|
||||
#endif
|
||||
|
|
@ -65,12 +67,14 @@ static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMA
|
|||
|
||||
// clang-format off
|
||||
static const uint32_t texture_source_formats[] = {
|
||||
#ifdef SUPPORTS_YUV422
|
||||
#ifdef SUPPORT_YUV422
|
||||
DRM_FORMAT_NV21,
|
||||
DRM_FORMAT_YUYV,
|
||||
#endif
|
||||
#ifdef SUPPORT_FP16_AND_10BIT_ABGR
|
||||
DRM_FORMAT_ABGR2101010,
|
||||
DRM_FORMAT_ABGR16161616F,
|
||||
#endif
|
||||
DRM_FORMAT_NV12,
|
||||
DRM_FORMAT_YVU420,
|
||||
DRM_FORMAT_YVU420_ANDROID
|
||||
|
|
@ -100,17 +104,18 @@ static int mediatek_init(struct driver *drv)
|
|||
struct format_metadata metadata;
|
||||
|
||||
drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
|
||||
&LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
|
||||
&LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK | BO_USE_SCANOUT | BO_USE_PROTECTED);
|
||||
|
||||
drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
|
||||
&LINEAR_METADATA, BO_USE_TEXTURE_MASK);
|
||||
&LINEAR_METADATA, BO_USE_TEXTURE_MASK | BO_USE_PROTECTED);
|
||||
|
||||
drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, BO_USE_SW_MASK | BO_USE_LINEAR);
|
||||
drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_PROTECTED);
|
||||
|
||||
/* YUYV format for video overlay and camera subsystem. */
|
||||
drv_add_combination(drv, DRM_FORMAT_YUYV, &LINEAR_METADATA,
|
||||
BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | BO_USE_LINEAR |
|
||||
BO_USE_TEXTURE);
|
||||
BO_USE_TEXTURE | BO_USE_PROTECTED);
|
||||
|
||||
/* Android CTS tests require this. */
|
||||
drv_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
|
||||
|
|
@ -119,11 +124,11 @@ static int mediatek_init(struct driver *drv)
|
|||
metadata.tiling = TILE_TYPE_LINEAR;
|
||||
metadata.priority = 1;
|
||||
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);
|
||||
drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED);
|
||||
drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED);
|
||||
#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);
|
||||
drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -170,6 +175,13 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
*/
|
||||
const bool is_camera_preview =
|
||||
(bo->meta.use_flags & BO_USE_SCANOUT) && (bo->meta.use_flags & BO_USE_CAMERA_WRITE);
|
||||
const bool is_hw_video_encoder = bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER;
|
||||
/*
|
||||
* Android sends blobs for encoding in the shape of a single-row pixel buffer. Use R8 +
|
||||
* single row as a proxy for Android HAL_PIXEL_FORMAT_BLOB until a drm equivalent is
|
||||
* defined.
|
||||
*/
|
||||
const bool is_format_blob = format == DRM_FORMAT_R8 && height == 1;
|
||||
|
||||
if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) {
|
||||
errno = EINVAL;
|
||||
|
|
@ -191,7 +203,7 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
stride = ALIGN(stride, 64);
|
||||
#endif
|
||||
|
||||
if ((bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) || is_camera_preview) {
|
||||
if ((is_hw_video_encoder && !is_format_blob) || is_camera_preview) {
|
||||
uint32_t aligned_height = ALIGN(height, 32);
|
||||
uint32_t padding[DRV_MAX_PLANES] = { 0 };
|
||||
|
||||
|
|
@ -203,7 +215,23 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
|
||||
drv_bo_from_format_and_padding(bo, stride, 1, aligned_height, format, padding);
|
||||
} else {
|
||||
#ifdef SUPPORTS_YUV422
|
||||
#ifdef USE_EXTRA_PADDING_FOR_YVU420
|
||||
/*
|
||||
* Apply extra padding for YV12 if the height does not meet round up requirement and
|
||||
* the image is to be sampled by gpu.
|
||||
*/
|
||||
static const uint32_t required_round_up = 4;
|
||||
const uint32_t height_mod = height % required_round_up;
|
||||
const bool is_texture = bo->meta.use_flags & BO_USE_TEXTURE;
|
||||
/*
|
||||
* YVU420 and YVU420_ANDROID treatments have been aligned in mediatek backend. Check
|
||||
* both since gbm frontend still maps linear YVU420 to YVU420_ANDROID for other hw
|
||||
* backends.
|
||||
*/
|
||||
const bool is_format_yv12 =
|
||||
format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID;
|
||||
#endif
|
||||
#ifdef SUPPORT_YUV422
|
||||
/*
|
||||
* JPEG Encoder Accelerator requires 16x16 alignment. We want the buffer
|
||||
* from camera can be put in JEA directly so align the height to 16
|
||||
|
|
@ -215,17 +243,13 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
drv_bo_from_format(bo, stride, 1, height, format);
|
||||
|
||||
#ifdef USE_EXTRA_PADDING_FOR_YVU420
|
||||
/*
|
||||
* Apply extra padding for YV12 if the height does not meet round up requirement and
|
||||
* the image is to be sampled by gpu.
|
||||
*/
|
||||
static const uint32_t required_round_up = 4;
|
||||
const uint32_t height_mod = height % required_round_up;
|
||||
if ((format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID) &&
|
||||
(bo->meta.use_flags & BO_USE_TEXTURE) && height_mod) {
|
||||
if (is_format_yv12 && is_texture && height_mod) {
|
||||
const uint32_t height_padding = required_round_up - height_mod;
|
||||
const uint32_t y_padding =
|
||||
drv_size_from_format(format, bo->meta.strides[0], height_padding, 0);
|
||||
const uint32_t u_padding =
|
||||
drv_size_from_format(format, bo->meta.strides[2], height_padding, 2);
|
||||
const uint32_t vu_size = drv_bo_get_plane_size(bo, 2) * 2;
|
||||
|
||||
bo->meta.total_size += u_padding;
|
||||
|
||||
|
|
@ -233,9 +257,6 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
* Since we are not aligning Y, we must make sure that its padding fits
|
||||
* inside the rest of the space allocated for the V/U planes.
|
||||
*/
|
||||
const uint32_t y_padding =
|
||||
drv_size_from_format(format, bo->meta.strides[0], height_padding, 0);
|
||||
const uint32_t vu_size = drv_bo_get_plane_size(bo, 2) * 2;
|
||||
if (y_padding > vu_size) {
|
||||
/* Align with mali workaround to pad all 3 planes. */
|
||||
bo->meta.total_size += y_padding + u_padding;
|
||||
|
|
@ -246,14 +267,17 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
|
||||
gem_create.size = bo->meta.total_size;
|
||||
|
||||
/* For protected data buffer needs to be allocated from GEM */
|
||||
if (bo->meta.use_flags & BO_USE_PROTECTED)
|
||||
gem_create.flags |= DRM_MTK_GEM_CREATE_ENCRYPTED;
|
||||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_CREATE, &gem_create);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_MTK_GEM_CREATE failed (size=%" PRIu64 ")\n", gem_create.size);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = gem_create.handle;
|
||||
bo->handle.u32 = gem_create.handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -273,7 +297,7 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
struct mediatek_private_map_data *priv;
|
||||
void *addr = NULL;
|
||||
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
gem_map.handle = bo->handle.u32;
|
||||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_MAP_OFFSET, &gem_map);
|
||||
if (ret) {
|
||||
|
|
|
|||
10
msm.c
10
msm.c
|
|
@ -296,7 +296,6 @@ static int msm_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t he
|
|||
{
|
||||
struct drm_msm_gem_new req = { 0 };
|
||||
int ret;
|
||||
size_t i;
|
||||
|
||||
bo->meta.tiling = (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) ? MSM_UBWC_TILING : 0;
|
||||
msm_calculate_layout(bo);
|
||||
|
|
@ -310,12 +309,7 @@ static int msm_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t he
|
|||
return -errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Though we use only one plane, we need to set handle for
|
||||
* all planes to pass kernel checks
|
||||
*/
|
||||
for (i = 0; i < bo->meta.num_planes; i++)
|
||||
bo->handles[i].u32 = req.handle;
|
||||
bo->handle.u32 = req.handle;
|
||||
|
||||
bo->meta.format_modifier = modifier;
|
||||
return 0;
|
||||
|
|
@ -360,7 +354,7 @@ static void *msm_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
if (bo->meta.format_modifier)
|
||||
return MAP_FAILED;
|
||||
|
||||
req.handle = bo->handles[0].u32;
|
||||
req.handle = bo->handle.u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MSM_GEM_INFO, &req);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCLT_MSM_GEM_INFO failed with %s\n", strerror(errno));
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
uint32_t count)
|
||||
{
|
||||
int ret;
|
||||
size_t plane;
|
||||
struct drm_rockchip_gem_create gem_create = { 0 };
|
||||
uint64_t afbc_modifier;
|
||||
|
||||
|
|
@ -178,8 +177,7 @@ static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint
|
|||
return -errno;
|
||||
}
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = gem_create.handle;
|
||||
bo->handle.u32 = gem_create.handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -205,7 +203,7 @@ static void *rockchip_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
bo->meta.format_modifier == DRM_FORMAT_MOD_ROCKCHIP_AFBC)
|
||||
return MAP_FAILED;
|
||||
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
gem_map.handle = bo->handle.u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &gem_map);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET failed\n");
|
||||
|
|
|
|||
5
vc4.c
5
vc4.c
|
|
@ -74,8 +74,7 @@ static int vc4_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t he
|
|||
return -errno;
|
||||
}
|
||||
|
||||
for (plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = bo_create.handle;
|
||||
bo->handle.u32 = bo_create.handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -110,7 +109,7 @@ static void *vc4_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
int ret;
|
||||
struct drm_vc4_mmap_bo bo_map = { 0 };
|
||||
|
||||
bo_map.handle = bo->handles[0].u32;
|
||||
bo_map.handle = bo->handle.u32;
|
||||
ret = drmCommandWriteRead(bo->drv->fd, DRM_VC4_MMAP_BO, &bo_map, sizeof(bo_map));
|
||||
if (ret) {
|
||||
drv_loge("DRM_VC4_MMAP_BO failed\n");
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ struct cross_domain_private {
|
|||
void *ring_addr;
|
||||
struct drv_array *metadata_cache;
|
||||
pthread_mutex_t metadata_cache_lock;
|
||||
bool mt8183_camera_quirk_;
|
||||
};
|
||||
|
||||
static void cross_domain_release_private(struct driver *drv)
|
||||
|
|
@ -344,6 +345,10 @@ static int cross_domain_init(struct driver *drv)
|
|||
if (ret < 0)
|
||||
goto free_private;
|
||||
|
||||
const char *name;
|
||||
name = drv_get_os_option("ro.product.name");
|
||||
priv->mt8183_camera_quirk_ = name && !strcmp(name, "kukui");
|
||||
|
||||
// minigbm bookkeeping
|
||||
add_combinations(drv);
|
||||
return 0;
|
||||
|
|
@ -404,8 +409,7 @@ static int cross_domain_bo_create(struct bo *bo, uint32_t width, uint32_t height
|
|||
return -errno;
|
||||
}
|
||||
|
||||
for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = drm_rc_blob.bo_handle;
|
||||
bo->handle.u32 = drm_rc_blob.bo_handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -415,7 +419,7 @@ static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, uint32_t map_fl
|
|||
int ret;
|
||||
struct drm_virtgpu_map gem_map = { 0 };
|
||||
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
gem_map.handle = bo->handle.u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
|
||||
|
|
@ -427,6 +431,42 @@ static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, uint32_t map_fl
|
|||
gem_map.offset);
|
||||
}
|
||||
|
||||
static void cross_domain_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
|
||||
uint64_t use_flags, uint32_t *out_format,
|
||||
uint64_t *out_use_flags)
|
||||
{
|
||||
struct cross_domain_private *priv = drv->priv;
|
||||
*out_format = format;
|
||||
*out_use_flags = use_flags;
|
||||
|
||||
switch (format) {
|
||||
case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
|
||||
if (priv->mt8183_camera_quirk_ && (use_flags & BO_USE_CAMERA_READ) &&
|
||||
!(use_flags & BO_USE_SCANOUT)) {
|
||||
*out_format = DRM_FORMAT_MTISP_SXYZW10;
|
||||
break;
|
||||
}
|
||||
/* Common camera implementation defined format. */
|
||||
if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) {
|
||||
*out_format = DRM_FORMAT_NV12;
|
||||
} else {
|
||||
/* 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:
|
||||
/* Common flexible video format. */
|
||||
*out_format = DRM_FORMAT_NV12;
|
||||
break;
|
||||
case DRM_FORMAT_YVU420_ANDROID:
|
||||
*out_use_flags &= ~BO_USE_SCANOUT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const struct backend virtgpu_cross_domain = {
|
||||
.name = "virtgpu_cross_domain",
|
||||
.init = cross_domain_init,
|
||||
|
|
@ -436,5 +476,5 @@ const struct backend virtgpu_cross_domain = {
|
|||
.bo_destroy = drv_gem_bo_destroy,
|
||||
.bo_map = cross_domain_bo_map,
|
||||
.bo_unmap = drv_bo_munmap,
|
||||
.resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper,
|
||||
.resolve_format_and_use_flags = cross_domain_resolve_format_and_use_flags,
|
||||
};
|
||||
|
|
|
|||
204
virtgpu_virgl.c
204
virtgpu_virgl.c
|
|
@ -7,6 +7,7 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -53,11 +54,23 @@ static const uint32_t texture_source_formats[] = {
|
|||
|
||||
extern struct virtgpu_param params[];
|
||||
|
||||
struct virgl_blob_metadata_cache {
|
||||
struct lru_entry entry;
|
||||
struct bo_metadata meta;
|
||||
};
|
||||
|
||||
#define lru_entry_to_metadata(entry) ((struct virgl_blob_metadata_cache *)(void *)(entry))
|
||||
|
||||
#define MAX_CACHED_FORMATS 128
|
||||
|
||||
struct virgl_priv {
|
||||
int caps_is_v2;
|
||||
union virgl_caps caps;
|
||||
int host_gbm_enabled;
|
||||
atomic_int next_blob_id;
|
||||
|
||||
pthread_mutex_t host_blob_format_lock;
|
||||
struct lru virgl_blob_metadata_cache;
|
||||
};
|
||||
|
||||
static uint32_t translate_format(uint32_t drm_fourcc)
|
||||
|
|
@ -499,8 +512,7 @@ static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui
|
|||
return ret;
|
||||
}
|
||||
|
||||
for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = res_create.bo_handle;
|
||||
bo->handle.u32 = res_create.bo_handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -510,7 +522,7 @@ static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
|
|||
int ret;
|
||||
struct drm_virtgpu_map gem_map = { 0 };
|
||||
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
gem_map.handle = bo->handle.u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map);
|
||||
if (ret) {
|
||||
drv_loge("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
|
||||
|
|
@ -592,7 +604,12 @@ static int virgl_init(struct driver *drv)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
int ret = pthread_mutex_init(&priv->host_blob_format_lock, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drv->priv = priv;
|
||||
lru_init(&priv->virgl_blob_metadata_cache, MAX_CACHED_FORMATS);
|
||||
|
||||
virgl_init_params_and_caps(drv);
|
||||
|
||||
|
|
@ -677,41 +694,56 @@ static void virgl_close(struct driver *drv)
|
|||
drv->priv = NULL;
|
||||
}
|
||||
|
||||
static int virgl_bo_create_blob(struct driver *drv, struct bo *bo)
|
||||
static uint32_t blob_flags_from_use_flags(uint32_t use_flags)
|
||||
{
|
||||
int ret;
|
||||
uint32_t stride;
|
||||
uint32_t cur_blob_id;
|
||||
uint32_t cmd[VIRGL_PIPE_RES_CREATE_SIZE + 1] = { 0 };
|
||||
struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
|
||||
uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE;
|
||||
if (bo->meta.use_flags & (BO_USE_SW_MASK | BO_USE_GPU_DATA_BUFFER))
|
||||
if (use_flags & (BO_USE_SW_MASK | BO_USE_GPU_DATA_BUFFER))
|
||||
blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
|
||||
|
||||
// For now, all blob use cases are cross device. When we add wider
|
||||
// support for blobs, we can revisit making this unconditional.
|
||||
blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE;
|
||||
|
||||
return blob_flags;
|
||||
}
|
||||
|
||||
static bool virgl_blob_metadata_eq(struct lru_entry *entry, void *data)
|
||||
{
|
||||
struct virgl_blob_metadata_cache *e = lru_entry_to_metadata(entry);
|
||||
struct bo_metadata *meta = data;
|
||||
uint32_t virgl_format1 = translate_format(e->meta.format);
|
||||
uint32_t virgl_format2 = translate_format(meta->format);
|
||||
|
||||
return e->meta.height == meta->height && e->meta.width == meta->width &&
|
||||
e->meta.use_flags == meta->use_flags && virgl_format1 == virgl_format2;
|
||||
}
|
||||
|
||||
static int virgl_blob_do_create(struct driver *drv, uint32_t width, uint32_t height,
|
||||
uint32_t use_flags, uint32_t virgl_format, uint32_t total_size,
|
||||
uint32_t *bo_handle)
|
||||
{
|
||||
int ret;
|
||||
uint32_t cur_blob_id;
|
||||
uint32_t cmd[VIRGL_PIPE_RES_CREATE_SIZE + 1] = { 0 };
|
||||
struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
uint32_t virgl_bind_flags = compute_virgl_bind_flags(use_flags);
|
||||
uint32_t blob_flags = blob_flags_from_use_flags(use_flags);
|
||||
|
||||
cur_blob_id = atomic_fetch_add(&priv->next_blob_id, 1);
|
||||
stride = drv_stride_from_format(bo->meta.format, bo->meta.width, 0);
|
||||
drv_bo_from_format(bo, stride, 1, bo->meta.height, bo->meta.format);
|
||||
bo->meta.total_size = ALIGN(bo->meta.total_size, PAGE_SIZE);
|
||||
bo->meta.tiling = blob_flags;
|
||||
|
||||
cmd[0] = VIRGL_CMD0(VIRGL_CCMD_PIPE_RESOURCE_CREATE, 0, VIRGL_PIPE_RES_CREATE_SIZE);
|
||||
cmd[VIRGL_PIPE_RES_CREATE_TARGET] = PIPE_TEXTURE_2D;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_WIDTH] = bo->meta.width;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_HEIGHT] = bo->meta.height;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_FORMAT] = translate_format(bo->meta.format);
|
||||
cmd[VIRGL_PIPE_RES_CREATE_BIND] = compute_virgl_bind_flags(bo->meta.use_flags);
|
||||
cmd[VIRGL_PIPE_RES_CREATE_WIDTH] = width;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_HEIGHT] = height;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_FORMAT] = virgl_format;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_BIND] = virgl_bind_flags;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_DEPTH] = 1;
|
||||
cmd[VIRGL_PIPE_RES_CREATE_BLOB_ID] = cur_blob_id;
|
||||
|
||||
drm_rc_blob.cmd = (uint64_t)&cmd;
|
||||
drm_rc_blob.cmd_size = 4 * (VIRGL_PIPE_RES_CREATE_SIZE + 1);
|
||||
drm_rc_blob.size = bo->meta.total_size;
|
||||
drm_rc_blob.size = total_size;
|
||||
drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D;
|
||||
drm_rc_blob.blob_flags = blob_flags;
|
||||
drm_rc_blob.blob_id = cur_blob_id;
|
||||
|
|
@ -722,8 +754,119 @@ static int virgl_bo_create_blob(struct driver *drv, struct bo *bo)
|
|||
return -errno;
|
||||
}
|
||||
|
||||
for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = drm_rc_blob.bo_handle;
|
||||
*bo_handle = drm_rc_blob.bo_handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Queries the host layout for the requested buffer metadata.
|
||||
//
|
||||
// Of particular interest is total_size. This value is passed to the kernel when creating
|
||||
// a buffer via drm_virtgpu_resource_create_blob.size, to specify how much "vram" to
|
||||
// allocate for use when exposing the host buffer to the guest. As such, we need to know
|
||||
// this value before allocating a buffer to ensure that the full host buffer is actually
|
||||
// visible to the guest.
|
||||
//
|
||||
// Note that we can't reuse these test buffers as actual allocations because our guess for
|
||||
// total_size is insufficient if width!=stride or padding!=0.
|
||||
static int virgl_blob_get_host_format(struct driver *drv, struct bo_metadata *meta)
|
||||
{
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
int num_planes = drv_num_planes_from_format(meta->format);
|
||||
|
||||
pthread_mutex_lock(&priv->host_blob_format_lock);
|
||||
if (meta->format == DRM_FORMAT_R8) {
|
||||
meta->offsets[0] = 0;
|
||||
meta->sizes[0] = meta->width;
|
||||
meta->strides[0] = meta->width;
|
||||
meta->total_size = meta->width;
|
||||
} else {
|
||||
uint32_t virgl_format = translate_format(meta->format);
|
||||
struct virgl_blob_metadata_cache *entry;
|
||||
|
||||
entry = lru_entry_to_metadata(
|
||||
lru_find(&priv->virgl_blob_metadata_cache, virgl_blob_metadata_eq, meta));
|
||||
|
||||
if (!entry) {
|
||||
uint32_t total_size = 0;
|
||||
for (int i = 0; i < num_planes; i++) {
|
||||
uint32_t stride =
|
||||
drv_stride_from_format(meta->format, meta->width, i);
|
||||
total_size +=
|
||||
drv_size_from_format(meta->format, stride, meta->height, i);
|
||||
}
|
||||
|
||||
uint32_t handle;
|
||||
int ret =
|
||||
virgl_blob_do_create(drv, meta->width, meta->height, meta->use_flags,
|
||||
virgl_format, total_size, &handle);
|
||||
if (ret) {
|
||||
pthread_mutex_unlock(&priv->host_blob_format_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct drm_virtgpu_resource_info_cros info = { 0 };
|
||||
info.bo_handle = handle;
|
||||
info.type = VIRTGPU_RESOURCE_INFO_TYPE_EXTENDED;
|
||||
int info_ret =
|
||||
drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO_CROS, &info);
|
||||
|
||||
struct drm_gem_close gem_close = { 0 };
|
||||
gem_close.handle = handle;
|
||||
int close_ret = drmIoctl(drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
if (close_ret)
|
||||
drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
|
||||
handle, close_ret);
|
||||
|
||||
if (info_ret) {
|
||||
pthread_mutex_unlock(&priv->host_blob_format_lock);
|
||||
drv_loge("Getting resource info failed with %s\n", strerror(errno));
|
||||
return info_ret;
|
||||
}
|
||||
|
||||
entry = calloc(1, sizeof(*entry));
|
||||
entry->meta = *meta;
|
||||
|
||||
for (int i = 0; i < num_planes; i++) {
|
||||
entry->meta.strides[i] = info.strides[i];
|
||||
entry->meta.sizes[i] =
|
||||
info.strides[i] *
|
||||
drv_height_from_format(meta->format, meta->height, i);
|
||||
entry->meta.offsets[i] = info.offsets[i];
|
||||
}
|
||||
entry->meta.total_size =
|
||||
entry->meta.offsets[num_planes - 1] + entry->meta.sizes[num_planes - 1];
|
||||
entry->meta.format_modifier = info.format_modifier;
|
||||
|
||||
lru_insert(&priv->virgl_blob_metadata_cache, &entry->entry);
|
||||
}
|
||||
|
||||
memcpy(meta->offsets, entry->meta.offsets, sizeof(meta->offsets));
|
||||
memcpy(meta->sizes, entry->meta.sizes, sizeof(meta->sizes));
|
||||
memcpy(meta->strides, entry->meta.strides, sizeof(meta->strides));
|
||||
meta->total_size = entry->meta.total_size;
|
||||
meta->format_modifier = entry->meta.format_modifier;
|
||||
}
|
||||
pthread_mutex_unlock(&priv->host_blob_format_lock);
|
||||
|
||||
meta->total_size = ALIGN(meta->total_size, PAGE_SIZE);
|
||||
meta->tiling = blob_flags_from_use_flags(meta->use_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virgl_bo_create_blob(struct driver *drv, struct bo *bo)
|
||||
{
|
||||
int ret;
|
||||
uint32_t virgl_format = translate_format(bo->meta.format);
|
||||
uint32_t bo_handle;
|
||||
|
||||
virgl_blob_get_host_format(drv, &bo->meta);
|
||||
ret = virgl_blob_do_create(drv, bo->meta.width, bo->meta.height, bo->meta.use_flags,
|
||||
virgl_format, bo->meta.total_size, &bo_handle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bo->handle.u32 = bo_handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -751,10 +894,17 @@ static bool should_use_blob(struct driver *drv, uint32_t format, uint64_t use_fl
|
|||
case DRM_FORMAT_R8:
|
||||
// Formats with strictly defined strides are supported
|
||||
return true;
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
// Formats used with frequent software reads are supported as long as they
|
||||
// will not be used by non-GPU hardware.
|
||||
return (use_flags & BO_USE_SW_READ_OFTEN) && !(use_flags & BO_USE_NON_GPU_HW);
|
||||
case DRM_FORMAT_YVU420_ANDROID:
|
||||
case DRM_FORMAT_NV12:
|
||||
// Knowing buffer metadata at buffer creation isn't yet supported, so buffers
|
||||
// can't be properly mapped into the guest.
|
||||
// Zero copy buffers are exposed for guest software access via a persistent
|
||||
// mapping, with no flush/invalidate messages. However, the virtio-video
|
||||
// device relies transfers to/from the host waiting on implicit fences in
|
||||
// the host kernel to synchronize with hardware output. As such, we can only
|
||||
// use zero copy if the guest doesn't need software access.
|
||||
return (use_flags & BO_USE_SW_MASK) == 0;
|
||||
default:
|
||||
return false;
|
||||
|
|
@ -815,7 +965,7 @@ static bool is_arc_screen_capture_bo(struct bo *bo)
|
|||
(bo->meta.format != DRM_FORMAT_ABGR8888 && bo->meta.format != DRM_FORMAT_ARGB8888 &&
|
||||
bo->meta.format != DRM_FORMAT_XRGB8888 && bo->meta.format != DRM_FORMAT_XBGR8888))
|
||||
return false;
|
||||
prime_handle.handle = bo->handles[0].u32;
|
||||
prime_handle.handle = bo->handle.u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
|
@ -1125,7 +1275,7 @@ static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
|
|||
if (!params[param_3d].value)
|
||||
return 0;
|
||||
|
||||
res_info.bo_handle = bo->handles[0].u32;
|
||||
res_info.bo_handle = bo->handle.u32;
|
||||
res_info.type = VIRTGPU_RESOURCE_INFO_TYPE_EXTENDED;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO_CROS, &res_info);
|
||||
if (ret) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue