Merge 'aosp/upstream-master' into 'aosp/master'

... to merge in http://crrev.com/c/2171157 which
is needed for Cuttlefish on Minigbm Gralloc 4.

Also adds OWNERS.android to avoid merge conflicts
with upstream OWNERS file.

Bug: b/146515640
Test: launch_cvd
Test: launch_cvd --gpu_mode=drm_virgl
Change-Id: I6dafb814cc47e3193439cc10af74a0099962813e
This commit is contained in:
Jason Macnak 2020-05-18 12:05:53 -07:00
commit 01b2926cf7
25 changed files with 743 additions and 169 deletions

12
OWNERS
View file

@ -1 +1,11 @@
adelva@google.com
dbehr@chromium.org
dcastagna@chromium.org
ddavenport@chromium.org
gurchetansingh@chromium.org
hoegsberg@chromium.org
ihf@chromium.org
lepton@chromium.org
marcheu@chromium.org
stevensd@chromium.org
tfiga@chromium.org
tutankhamen@chromium.org

2
OWNERS.android Normal file
View file

@ -0,0 +1,2 @@
adelva@google.com
natsu@google.com

108
amdgpu.c
View file

@ -18,13 +18,9 @@
#include "helpers.h"
#include "util.h"
#ifdef __ANDROID__
#define DRI_PATH "/vendor/lib/dri/radeonsi_dri.so"
#else
// clang-format off
#define DRI_PATH STRINGIZE(DRI_DRIVER_DIR/radeonsi_dri.so)
// clang-format on
#endif
#define TILE_TYPE_LINEAR 0
/* DRI backend decides tiling in this case. */
@ -39,8 +35,8 @@ const static uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMA
DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888 };
const static uint32_t texture_source_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_R8,
DRM_FORMAT_NV21, DRM_FORMAT_NV12,
const static uint32_t texture_source_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_R8,
DRM_FORMAT_NV21, DRM_FORMAT_NV12,
DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_YVU420 };
static int amdgpu_init(struct driver *drv)
@ -142,43 +138,13 @@ static void amdgpu_close(struct driver *drv)
drv->priv = NULL;
}
static int amdgpu_create_bo(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint64_t use_flags)
static int amdgpu_create_bo_linear(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint64_t use_flags)
{
int ret;
uint32_t plane, stride;
struct combination *combo;
union drm_amdgpu_gem_create gem_create;
combo = drv_get_combination(bo->drv, format, use_flags);
if (!combo)
return -EINVAL;
if (combo->metadata.tiling == TILE_TYPE_DRI) {
bool needs_alignment = false;
#ifdef __ANDROID__
/*
* Currently, the gralloc API doesn't differentiate between allocation time and map
* time strides. A workaround for amdgpu DRI buffers is to always to align to 256 at
* allocation time.
*
* See b/115946221,b/117942643
*/
if (use_flags & (BO_USE_SW_MASK))
needs_alignment = true;
#endif
// See b/122049612
if (use_flags & (BO_USE_SCANOUT))
needs_alignment = true;
if (needs_alignment) {
uint32_t bytes_per_pixel = drv_bytes_per_pixel_from_format(format, 0);
width = ALIGN(width, 256 / bytes_per_pixel);
}
return dri_bo_create(bo, width, height, format, use_flags);
}
stride = drv_stride_from_format(format, width, 0);
stride = ALIGN(stride, 256);
@ -210,14 +176,72 @@ static int amdgpu_create_bo(struct bo *bo, uint32_t width, uint32_t height, uint
return 0;
}
static int amdgpu_import_bo(struct bo *bo, struct drv_import_fd_data *data)
static int amdgpu_create_bo(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint64_t use_flags)
{
struct combination *combo;
combo = drv_get_combination(bo->drv, data->format, data->use_flags);
combo = drv_get_combination(bo->drv, format, use_flags);
if (!combo)
return -EINVAL;
if (combo->metadata.tiling == TILE_TYPE_DRI)
if (combo->metadata.tiling == TILE_TYPE_DRI) {
bool needs_alignment = false;
#ifdef __ANDROID__
/*
* Currently, the gralloc API doesn't differentiate between allocation time and map
* time strides. A workaround for amdgpu DRI buffers is to always to align to 256 at
* allocation time.
*
* See b/115946221,b/117942643
*/
if (use_flags & (BO_USE_SW_MASK))
needs_alignment = true;
#endif
// See b/122049612
if (use_flags & (BO_USE_SCANOUT))
needs_alignment = true;
if (needs_alignment) {
uint32_t bytes_per_pixel = drv_bytes_per_pixel_from_format(format, 0);
width = ALIGN(width, 256 / bytes_per_pixel);
}
return dri_bo_create(bo, width, height, format, use_flags);
}
return amdgpu_create_bo_linear(bo, width, height, format, use_flags);
}
static int amdgpu_create_bo_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
uint32_t format, const uint64_t *modifiers,
uint32_t count)
{
bool only_use_linear = true;
for (uint32_t i = 0; i < count; ++i)
if (modifiers[i] != DRM_FORMAT_MOD_LINEAR)
only_use_linear = false;
if (only_use_linear)
return amdgpu_create_bo_linear(bo, width, height, format, BO_USE_SCANOUT);
return dri_bo_create_with_modifiers(bo, width, height, format, modifiers, count);
}
static int amdgpu_import_bo(struct bo *bo, struct drv_import_fd_data *data)
{
bool dri_tiling = data->format_modifiers[0] != DRM_FORMAT_MOD_LINEAR;
if (data->format_modifiers[0] == DRM_FORMAT_MOD_INVALID) {
struct combination *combo;
combo = drv_get_combination(bo->drv, data->format, data->use_flags);
if (!combo)
return -EINVAL;
dri_tiling = combo->metadata.tiling == TILE_TYPE_DRI;
}
if (dri_tiling)
return dri_bo_import(bo, data);
else
return drv_prime_bo_import(bo, data);
@ -309,12 +333,14 @@ const struct backend backend_amdgpu = {
.init = amdgpu_init,
.close = amdgpu_close,
.bo_create = amdgpu_create_bo,
.bo_create_with_modifiers = amdgpu_create_bo_with_modifiers,
.bo_destroy = amdgpu_destroy_bo,
.bo_import = amdgpu_import_bo,
.bo_map = amdgpu_map_bo,
.bo_unmap = amdgpu_unmap_bo,
.bo_invalidate = amdgpu_bo_invalidate,
.resolve_format = amdgpu_resolve_format,
.num_planes_from_modifier = dri_num_planes_from_modifier,
};
#endif

View file

@ -108,3 +108,9 @@ int32_t cros_gralloc_buffer::unlock()
return 0;
}
int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
uint32_t offsets[DRV_MAX_PLANES])
{
return drv_resource_info(bo_, strides, offsets);
}

View file

@ -26,6 +26,7 @@ class cros_gralloc_buffer
int32_t lock(const struct rectangle *rect, uint32_t map_flags,
uint8_t *addr[DRV_MAX_PLANES]);
int32_t unlock();
int32_t resource_info(uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES]);
private:
cros_gralloc_buffer(cros_gralloc_buffer const &);

View file

@ -333,6 +333,26 @@ int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t
return 0;
}
int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
uint32_t offsets[DRV_MAX_PLANES])
{
std::lock_guard<std::mutex> lock(mutex_);
auto hnd = cros_gralloc_convert_handle(handle);
if (!hnd) {
drv_log("Invalid handle.\n");
return -EINVAL;
}
auto buffer = get_buffer(hnd);
if (!buffer) {
drv_log("Invalid Reference.\n");
return -EINVAL;
}
return buffer->resource_info(strides, offsets);
}
cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
{
/* Assumes driver mutex is held. */

View file

@ -31,6 +31,8 @@ class cros_gralloc_driver
int32_t unlock(buffer_handle_t handle, int32_t *release_fence);
int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store);
int32_t resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
uint32_t offsets[DRV_MAX_PLANES]);
private:
cros_gralloc_driver(cros_gralloc_driver const &);

View file

@ -4,6 +4,7 @@
* found in the LICENSE file.
*/
#include "../../util.h"
#include "../cros_gralloc_driver.h"
#include <cassert>
@ -261,6 +262,8 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...)
uint64_t *out_store;
buffer_handle_t handle;
uint32_t *out_width, *out_height, *out_stride;
uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
auto mod = (struct gralloc0_module const *)module;
switch (op) {
@ -286,7 +289,17 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...)
switch (op) {
case GRALLOC_DRM_GET_STRIDE:
out_stride = va_arg(args, uint32_t *);
*out_stride = hnd->pixel_stride;
ret = mod->driver->resource_info(handle, strides, offsets);
if (ret)
break;
if (strides[0] != hnd->strides[0]) {
uint32_t bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
*out_stride = DIV_ROUND_UP(strides[0], bytes_per_pixel);
} else {
*out_stride = hnd->pixel_stride;
}
break;
case GRALLOC_DRM_GET_FORMAT:
out_format = va_arg(args, int32_t *);
@ -364,6 +377,8 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
{
int32_t ret;
uint32_t map_flags;
uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr };
auto mod = (struct gralloc0_module const *)module;
struct rectangle rect = { .x = static_cast<uint32_t>(l),
@ -393,13 +408,23 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
if (ret)
return ret;
if (!map_flags) {
ret = mod->driver->resource_info(handle, strides, offsets);
if (ret)
return ret;
for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++)
addr[plane] =
reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(offsets[plane]));
}
switch (hnd->format) {
case DRM_FORMAT_NV12:
ycbcr->y = addr[0];
ycbcr->cb = addr[1];
ycbcr->cr = addr[1] + 1;
ycbcr->ystride = hnd->strides[0];
ycbcr->cstride = hnd->strides[1];
ycbcr->ystride = (!map_flags) ? strides[0] : hnd->strides[0];
ycbcr->cstride = (!map_flags) ? strides[1] : hnd->strides[1];
ycbcr->chroma_step = 2;
break;
case DRM_FORMAT_YVU420:
@ -407,8 +432,8 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
ycbcr->y = addr[0];
ycbcr->cb = addr[2];
ycbcr->cr = addr[1];
ycbcr->ystride = hnd->strides[0];
ycbcr->cstride = hnd->strides[1];
ycbcr->ystride = (!map_flags) ? strides[0] : hnd->strides[0];
ycbcr->cstride = (!map_flags) ? strides[1] : hnd->strides[1];
ycbcr->chroma_step = 1;
break;
default:

View file

@ -95,7 +95,7 @@ static struct combinations combos[] = {
// clang-format on
struct grallocinfo {
buffer_handle_t handle; /* handle to the buffer */
buffer_handle_t handle; /* handle to the buffer */
int w; /* width of buffer */
int h; /* height of buffer */
int format; /* format of the buffer */

257
dri.c
View file

@ -64,29 +64,6 @@ static bool lookup_extension(const __DRIextension *const *extensions, const char
return false;
}
/*
* 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 prime_fd, ret;
if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_FD, &prime_fd))
return -errno;
ret = drmPrimeFDToHandle(bo->drv->fd, prime_fd, &handle);
if (ret) {
drv_log("drmPrimeFDToHandle failed with %s\n", strerror(errno));
return ret;
}
bo->handles[0].u32 = handle;
close(prime_fd);
return 0;
}
/*
* Close Gem Handle
*/
@ -102,6 +79,118 @@ static void close_gem_handle(uint32_t handle, int fd)
drv_log("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];
__DRIimage *plane_image = NULL;
if (dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
&modifier_upper) &&
dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
&modifier_lower)) {
bo->meta.format_modifiers[0] =
((uint64_t)modifier_upper << 32) | (uint32_t)modifier_lower;
} else {
bo->meta.format_modifiers[0] = DRM_FORMAT_MOD_INVALID;
}
if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_NUM_PLANES,
&num_planes)) {
return -errno;
}
bo->meta.num_planes = num_planes;
for (i = 0; i < num_planes; ++i) {
int prime_fd, stride, offset;
plane_image = dri->image_extension->fromPlanar(bo->priv, i, NULL);
__DRIimage *image = plane_image ? plane_image : bo->priv;
if (i)
bo->meta.format_modifiers[i] = bo->meta.format_modifiers[0];
if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride) ||
!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET, &offset)) {
ret = -errno;
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_log("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);
}
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];
}
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;
/* 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;
}
/*
* The caller is responsible for setting drv->priv to a structure that derives from dri_driver.
*/
@ -190,11 +279,9 @@ int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t forma
uint64_t use_flags)
{
unsigned int dri_use;
int ret, dri_format, stride, offset;
int modifier_upper, modifier_lower;
int ret, dri_format;
struct dri_driver *dri = bo->drv->priv;
assert(bo->meta.num_planes == 1);
dri_format = drm_format_to_dri_format(format);
/* Gallium drivers require shared to get the handle and stride. */
@ -217,34 +304,38 @@ int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t forma
if (ret)
goto free_image;
if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_STRIDE, &stride)) {
ret = -errno;
goto close_handle;
}
if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_OFFSET, &offset)) {
ret = -errno;
goto close_handle;
}
if (dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
&modifier_upper) &&
dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
&modifier_lower)) {
bo->meta.format_modifiers[0] =
((uint64_t)modifier_upper << 32) | (uint32_t)modifier_lower;
} else {
bo->meta.format_modifiers[0] = DRM_FORMAT_MOD_INVALID;
}
bo->meta.strides[0] = stride;
bo->meta.sizes[0] = stride * height;
bo->meta.offsets[0] = offset;
bo->meta.total_size = offset + bo->meta.sizes[0];
return 0;
close_handle:
close_gem_handle(bo->handles[0].u32, bo->drv->fd);
free_image:
dri->image_extension->destroyImage(bo->priv);
return ret;
}
int dri_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
const uint64_t *modifiers, uint32_t modifier_count)
{
int ret, dri_format;
struct dri_driver *dri = bo->drv->priv;
if (!dri->image_extension->createImageWithModifiers) {
return -ENOENT;
}
dri_format = drm_format_to_dri_format(format);
bo->priv = dri->image_extension->createImageWithModifiers(
dri->device, width, height, dri_format, modifiers, modifier_count, NULL);
if (!bo->priv) {
ret = -errno;
return ret;
}
ret = import_into_minigbm(dri, bo);
if (ret)
goto free_image;
return 0;
free_image:
dri->image_extension->destroyImage(bo->priv);
return ret;
@ -255,17 +346,41 @@ int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data)
int ret;
struct dri_driver *dri = bo->drv->priv;
assert(bo->meta.num_planes == 1);
if (data->format_modifiers[0] != DRM_FORMAT_MOD_INVALID) {
unsigned error;
// clang-format off
bo->priv = dri->image_extension->createImageFromFds(dri->device, data->width, data->height,
data->format, data->fds,
bo->meta.num_planes,
(int *)data->strides,
(int *)data->offsets, NULL);
// clang-format on
if (!bo->priv)
return -errno;
if (!dri->image_extension->createImageFromDmaBufs2)
return -ENOSYS;
// clang-format off
bo->priv = dri->image_extension->createImageFromDmaBufs2(dri->device, data->width, data->height,
data->format,
data->format_modifiers[0],
data->fds,
bo->meta.num_planes,
(int *)data->strides,
(int *)data->offsets,
__DRI_YUV_COLOR_SPACE_UNDEFINED,
__DRI_YUV_RANGE_UNDEFINED,
__DRI_YUV_CHROMA_SITING_UNDEFINED,
__DRI_YUV_CHROMA_SITING_UNDEFINED,
&error, NULL);
// clang-format on
/* Could translate the DRI error, but the Mesa GBM also returns ENOSYS. */
if (!bo->priv)
return -ENOSYS;
} else {
// clang-format off
bo->priv = dri->image_extension->createImageFromFds(dri->device, data->width, data->height,
data->format, data->fds,
bo->meta.num_planes,
(int *)data->strides,
(int *)data->offsets, NULL);
// clang-format on
if (!bo->priv)
return -errno;
}
ret = import_into_minigbm(dri, bo);
if (ret) {
@ -329,4 +444,22 @@ int dri_bo_unmap(struct bo *bo, struct vma *vma)
return 0;
}
size_t dri_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier)
{
struct dri_driver *dri = drv->priv;
if (!dri->image_extension->queryDmaBufFormatModifierAttribs) {
/* We do not do any modifier checks here. The create will fail
* later if the modifier is not supported. */
return drv_num_planes_from_format(format);
}
uint64_t planes;
GLboolean ret = dri->image_extension->queryDmaBufFormatModifierAttribs(
dri->device, format, modifier, __DRI_IMAGE_ATTRIB_NUM_PLANES, &planes);
if (!ret)
return 0;
return planes;
}
#endif

3
dri.h
View file

@ -30,9 +30,12 @@ int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suf
void dri_close(struct driver *drv);
int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint64_t use_flags);
int dri_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
const uint64_t *modifiers, uint32_t modifier_count);
int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data);
int dri_bo_destroy(struct bo *bo);
void *dri_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
int dri_bo_unmap(struct bo *bo, struct vma *vma);
size_t dri_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier);
#endif

27
drv.c
View file

@ -54,6 +54,9 @@ extern const struct backend backend_radeon;
#ifdef DRV_ROCKCHIP
extern const struct backend backend_rockchip;
#endif
#ifdef DRV_SYNAPTICS
extern const struct backend backend_synaptics;
#endif
#ifdef DRV_TEGRA
extern const struct backend backend_tegra;
#endif
@ -104,6 +107,9 @@ static const struct backend *drv_get_backend(int fd)
#ifdef DRV_ROCKCHIP
&backend_rockchip,
#endif
#ifdef DRV_SYNAPTICS
&backend_synaptics,
#endif
#ifdef DRV_TEGRA
&backend_tegra,
#endif
@ -111,7 +117,7 @@ static const struct backend *drv_get_backend(int fd)
#ifdef DRV_VC4
&backend_vc4,
#endif
&backend_vgem, &backend_virtio_gpu,
&backend_vgem, &backend_virtio_gpu,
};
for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
@ -278,11 +284,8 @@ struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, ui
if (drv->backend->bo_compute_metadata) {
ret = drv->backend->bo_compute_metadata(bo, width, height, format, use_flags, NULL,
0);
if (!is_test_alloc && ret == 0) {
if (!is_test_alloc && ret == 0)
ret = drv->backend->bo_create_from_metadata(bo);
if (ret == 0)
return bo;
}
} else if (!is_test_alloc) {
ret = drv->backend->bo_create(bo, width, height, format, use_flags);
}
@ -688,3 +691,17 @@ void drv_log_prefix(const char *prefix, const char *file, int line, const char *
#endif
va_end(args);
}
int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
uint32_t offsets[DRV_MAX_PLANES])
{
for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
strides[plane] = bo->meta.strides[plane];
offsets[plane] = bo->meta.offsets[plane];
}
if (bo->drv->backend->resource_info)
return bo->drv->backend->resource_info(bo, strides, offsets);
return 0;
}

5
drv.h
View file

@ -175,8 +175,13 @@ uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_fl
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]);
#define drv_log(format, ...) \
do { \
drv_log_prefix("minigbm", __FILE__, __LINE__, format, ##__VA_ARGS__); \

View file

@ -79,6 +79,9 @@ struct backend {
int (*bo_invalidate)(struct bo *bo, struct mapping *mapping);
int (*bo_flush)(struct bo *bo, struct mapping *mapping);
uint32_t (*resolve_format)(struct driver *drv, uint32_t format, uint64_t use_flags);
size_t (*num_planes_from_modifier)(struct driver *drv, uint32_t format, uint64_t modifier);
int (*resource_info)(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
uint32_t offsets[DRV_MAX_PLANES]);
};
// clang-format off

6
gbm.c
View file

@ -210,13 +210,17 @@ PUBLIC struct gbm_bo *gbm_bo_import(struct gbm_device *gbm, uint32_t type, void
drv_data.format = fd_data->format;
drv_data.fds[0] = fd_data->fd;
drv_data.strides[0] = fd_data->stride;
for (i = 0; i < GBM_MAX_PLANES; ++i)
drv_data.format_modifiers[i] = DRM_FORMAT_MOD_INVALID;
break;
case GBM_BO_IMPORT_FD_MODIFIER:
gbm_format = fd_modifier_data->format;
drv_data.width = fd_modifier_data->width;
drv_data.height = fd_modifier_data->height;
drv_data.format = fd_modifier_data->format;
num_planes = drv_num_planes_from_format(drv_data.format);
num_planes = drv_num_planes_from_modifier(gbm->drv, drv_data.format,
fd_modifier_data->modifier);
assert(num_planes);
num_fds = fd_modifier_data->num_fds;

View file

@ -176,6 +176,20 @@ size_t drv_num_planes_from_format(uint32_t format)
return layout ? layout->num_planes : 0;
}
size_t drv_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier)
{
size_t planes = drv_num_planes_from_format(format);
/* Disallow unsupported formats. */
if (!planes)
return 0;
if (drv->backend->num_planes_from_modifier && modifier != DRM_FORMAT_MOD_INVALID)
return drv->backend->num_planes_from_modifier(drv, format, modifier);
return planes;
}
uint32_t drv_height_from_format(uint32_t format, uint32_t height, size_t plane)
{
const struct planar_layout *layout = layout_from_format(format);
@ -299,14 +313,17 @@ int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32
aligned_height = height;
switch (format) {
case DRM_FORMAT_YVU420_ANDROID:
/* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not
* be aligned. Update 'height' so that drv_bo_from_format below
* uses the non-aligned height. */
height = bo->meta.height;
/* Align width to 32 pixels, so chroma strides are 16 bytes as
* Android requires. */
aligned_width = ALIGN(width, 32);
/* Adjust the height to include room for chroma planes.
*
* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not
* be aligned. */
aligned_height = 3 * DIV_ROUND_UP(bo->meta.height, 2);
/* Adjust the height to include room for chroma planes. */
aligned_height = 3 * DIV_ROUND_UP(height, 2);
break;
case DRM_FORMAT_YVU420:
case DRM_FORMAT_NV12:

4
i915.c
View file

@ -116,7 +116,8 @@ static int i915_add_combinations(struct driver *drv)
metadata.priority = 3;
metadata.modifier = I915_FORMAT_MOD_Y_TILED;
scanout_and_render = unset_flags(scanout_and_render, BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY);
scanout_and_render =
unset_flags(scanout_and_render, BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY);
/* Support y-tiled NV12 and P010 for libva */
#ifdef I915_SCANOUT_Y_TILED
drv_add_combination(drv, DRM_FORMAT_NV12, &metadata,
@ -272,7 +273,6 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig
uint64_t use_flags, const uint64_t *modifiers, uint32_t count)
{
static const uint64_t modifier_order[] = {
I915_FORMAT_MOD_Y_TILED_CCS,
I915_FORMAT_MOD_Y_TILED,
I915_FORMAT_MOD_X_TILED,
DRM_FORMAT_MOD_LINEAR,

View file

@ -49,7 +49,7 @@ 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);
&LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
&LINEAR_METADATA, BO_USE_TEXTURE_MASK);
@ -178,8 +178,8 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3
return MAP_FAILED;
}
ret = drmPrimeHandleToFD(bo->drv->fd, gem_map.handle, DRM_CLOEXEC, &prime_fd);
if (ret) {
prime_fd = drv_bo_get_plane_fd(bo, 0);
if (prime_fd < 0) {
drv_log("Failed to get a prime fd\n");
return MAP_FAILED;
}

View file

@ -10,12 +10,14 @@
#include "helpers.h"
#include "util.h"
static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888,
DRM_FORMAT_BGR888, DRM_FORMAT_BGR565};
static int meson_init(struct driver *drv)
{
drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
&LINEAR_METADATA, BO_USE_RENDER_MASK);
drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
&LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
return drv_modify_linear_combinations(drv);
}

2
msm.c
View file

@ -109,7 +109,7 @@ static void msm_calculate_layout(struct bo *bo)
DRM_FORMAT_R8 of height one is used for JPEG camera output, so don't
height align that. */
if (bo->meta.format == DRM_FORMAT_YVU420_ANDROID ||
(bo->meta.format == DRM_FORMAT_R8 && height == 1)) {
(bo->meta.format == DRM_FORMAT_R8 && height == 1)) {
alignh = height;
} else {
alignh = ALIGN(height, DEFAULT_ALIGNMENT);

View file

@ -4,5 +4,6 @@
# found in the LICENSE file.
find \
'(' -name '*.[ch]' -or -name '*.cc' ')' \
-not -name 'virtgpu_drm.h' \
-not -name 'gbm.h' -not -name 'virgl_hw.h' \
-exec clang-format -style=file -i {} +

39
synaptics.c Normal file
View file

@ -0,0 +1,39 @@
/*
* Copyright 2020 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.
*/
#ifdef DRV_SYNAPTICS
#include "drv_priv.h"
#include "helpers.h"
#include "util.h"
static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
DRM_FORMAT_XRGB8888 };
static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12,
DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
static int synaptics_init(struct driver *drv)
{
drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
&LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
&LINEAR_METADATA, BO_USE_TEXTURE_MASK | BO_USE_HW_VIDEO_ENCODER);
return drv_modify_linear_combinations(drv);
}
const struct backend backend_synaptics = {
.name = "synaptics",
.init = synaptics_init,
.bo_create = drv_dumb_bo_create,
.bo_destroy = drv_dumb_bo_destroy,
.bo_import = drv_prime_bo_import,
.bo_map = drv_dumb_bo_map,
.bo_unmap = drv_bo_munmap,
};
#endif

40
vc4.c
View file

@ -28,14 +28,24 @@ static int vc4_init(struct driver *drv)
return drv_modify_linear_combinations(drv);
}
static int vc4_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint64_t use_flags)
static int vc4_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t height,
uint32_t format, uint64_t modifier)
{
int ret;
size_t plane;
uint32_t stride;
struct drm_vc4_create_bo bo_create;
switch (modifier) {
case DRM_FORMAT_MOD_LINEAR:
break;
case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
drv_log("DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED not supported yet\n");
return -EINVAL;
default:
return -EINVAL;
}
/*
* Since the ARM L1 cache line size is 64 bytes, align to that as a
* performance optimization.
@ -59,6 +69,31 @@ static int vc4_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_
return 0;
}
static int vc4_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint64_t use_flags)
{
struct combination *combo;
combo = drv_get_combination(bo->drv, format, use_flags);
if (!combo)
return -EINVAL;
return vc4_bo_create_for_modifier(bo, width, height, format, combo->metadata.modifier);
}
static int vc4_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
uint32_t format, const uint64_t *modifiers, uint32_t count)
{
static const uint64_t modifier_order[] = {
DRM_FORMAT_MOD_LINEAR,
};
uint64_t modifier;
modifier = drv_pick_modifier(modifiers, count, modifier_order, ARRAY_SIZE(modifier_order));
return vc4_bo_create_for_modifier(bo, width, height, format, modifier);
}
static void *vc4_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
{
int ret;
@ -82,6 +117,7 @@ const struct backend backend_vc4 = {
.name = "vc4",
.init = vc4_init,
.bo_create = vc4_bo_create,
.bo_create_with_modifiers = vc4_bo_create_with_modifiers,
.bo_import = drv_prime_bo_import,
.bo_destroy = drv_gem_bo_destroy,
.bo_map = vc4_bo_map,

188
virtgpu_drm.h Normal file
View file

@ -0,0 +1,188 @@
/*
* Copyright 2013 Red Hat
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef VIRTGPU_DRM_H
#define VIRTGPU_DRM_H
#include "drm.h"
#if defined(__cplusplus)
extern "C" {
#endif
/* Please note that modifications to all structs defined here are
* subject to backwards-compatibility constraints.
*
* Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel
* compatibility Keep fields aligned to their size
*/
#define DRM_VIRTGPU_MAP 0x01
#define DRM_VIRTGPU_EXECBUFFER 0x02
#define DRM_VIRTGPU_GETPARAM 0x03
#define DRM_VIRTGPU_RESOURCE_CREATE 0x04
#define DRM_VIRTGPU_RESOURCE_INFO 0x05
#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x06
#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07
#define DRM_VIRTGPU_WAIT 0x08
#define DRM_VIRTGPU_GET_CAPS 0x09
#define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01
#define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02
#define VIRTGPU_EXECBUF_FLAGS (\
VIRTGPU_EXECBUF_FENCE_FD_IN |\
VIRTGPU_EXECBUF_FENCE_FD_OUT |\
0)
struct drm_virtgpu_map {
__u64 offset; /* use for mmap system call */
__u32 handle;
__u32 pad;
};
struct drm_virtgpu_execbuffer {
__u32 flags;
__u32 size;
__u64 command; /* void* */
__u64 bo_handles;
__u32 num_bo_handles;
__s32 fence_fd; /* in/out fence fd (see VIRTGPU_EXECBUF_FENCE_FD_IN/OUT) */
};
#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */
struct drm_virtgpu_getparam {
__u64 param;
__u64 value;
};
/* NO_BO flags? NO resource flag? */
/* resource flag for y_0_top */
struct drm_virtgpu_resource_create {
__u32 target;
__u32 format;
__u32 bind;
__u32 width;
__u32 height;
__u32 depth;
__u32 array_size;
__u32 last_level;
__u32 nr_samples;
__u32 flags;
__u32 bo_handle; /* if this is set - recreate a new resource attached to this bo ? */
__u32 res_handle; /* returned by kernel */
__u32 size; /* validate transfer in the host */
__u32 stride; /* validate transfer in the host */
};
struct drm_virtgpu_resource_info {
__u32 bo_handle;
__u32 res_handle;
__u32 size;
union {
__u32 stride;
__u32 strides[4]; /* strides[0] is accessible with stride. */
};
__u32 num_planes;
__u32 offsets[4];
__u64 format_modifier;
};
struct drm_virtgpu_3d_box {
__u32 x;
__u32 y;
__u32 z;
__u32 w;
__u32 h;
__u32 d;
};
struct drm_virtgpu_3d_transfer_to_host {
__u32 bo_handle;
struct drm_virtgpu_3d_box box;
__u32 level;
__u32 offset;
};
struct drm_virtgpu_3d_transfer_from_host {
__u32 bo_handle;
struct drm_virtgpu_3d_box box;
__u32 level;
__u32 offset;
};
#define VIRTGPU_WAIT_NOWAIT 1 /* like it */
struct drm_virtgpu_3d_wait {
__u32 handle; /* 0 is an invalid handle */
__u32 flags;
};
struct drm_virtgpu_get_caps {
__u32 cap_set_id;
__u32 cap_set_ver;
__u64 addr;
__u32 size;
__u32 pad;
};
#define DRM_IOCTL_VIRTGPU_MAP \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map)
#define DRM_IOCTL_VIRTGPU_EXECBUFFER \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER,\
struct drm_virtgpu_execbuffer)
#define DRM_IOCTL_VIRTGPU_GETPARAM \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM,\
struct drm_virtgpu_getparam)
#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE, \
struct drm_virtgpu_resource_create)
#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \
struct drm_virtgpu_resource_info)
#define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST, \
struct drm_virtgpu_3d_transfer_from_host)
#define DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_TO_HOST, \
struct drm_virtgpu_3d_transfer_to_host)
#define DRM_IOCTL_VIRTGPU_WAIT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WAIT, \
struct drm_virtgpu_3d_wait)
#define DRM_IOCTL_VIRTGPU_GET_CAPS \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \
struct drm_virtgpu_get_caps)
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -9,13 +9,13 @@
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <virtgpu_drm.h>
#include <xf86drm.h>
#include "drv_priv.h"
#include "helpers.h"
#include "util.h"
#include "virgl_hw.h"
#include "virtgpu_drm.h"
#ifndef PAGE_SIZE
#define PAGE_SIZE 0x1000
@ -25,6 +25,27 @@
#define MESA_LLVMPIPE_TILE_ORDER 6
#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
struct feature {
uint64_t feature;
const char *name;
uint32_t enabled;
};
enum feature_id {
feat_3d,
feat_capset_fix,
feat_max,
};
#define FEATURE(x) \
(struct feature) \
{ \
x, #x, 0 \
}
static struct feature features[] = { FEATURE(VIRTGPU_PARAM_3D_FEATURES),
FEATURE(VIRTGPU_PARAM_CAPSET_QUERY_FIX) };
static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888 };
@ -37,7 +58,6 @@ static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_R
DRM_FORMAT_YVU420_ANDROID };
struct virtio_gpu_priv {
int has_3d;
int caps_is_v2;
union virgl_caps caps;
};
@ -89,7 +109,7 @@ static void virtio_gpu_add_combination(struct driver *drv, uint32_t drm_format,
{
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
if (priv->has_3d && priv->caps.max_version >= 1) {
if (features[feat_3d].enabled && priv->caps.max_version >= 1) {
if ((use_flags & BO_USE_RENDERING) &&
!virtio_gpu_supports_format(&priv->caps.v1.render, drm_format)) {
drv_log("Skipping unsupported render format: %d\n", drm_format);
@ -239,21 +259,11 @@ static int virtio_gpu_get_caps(struct driver *drv, union virgl_caps *caps, int *
{
int ret;
struct drm_virtgpu_get_caps cap_args;
struct drm_virtgpu_getparam param_args;
uint32_t can_query_v2 = 0;
memset(&param_args, 0, sizeof(param_args));
param_args.param = VIRTGPU_PARAM_CAPSET_QUERY_FIX;
param_args.value = (uint64_t)(uintptr_t)&can_query_v2;
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &param_args);
if (ret) {
drv_log("DRM_IOCTL_VIRTGPU_GETPARAM failed with %s\n", strerror(errno));
}
*caps_is_v2 = 0;
memset(&cap_args, 0, sizeof(cap_args));
cap_args.addr = (unsigned long long)caps;
if (can_query_v2) {
if (features[feat_capset_fix].enabled) {
*caps_is_v2 = 1;
cap_args.cap_set_id = 2;
cap_args.size = sizeof(union virgl_caps);
@ -284,22 +294,20 @@ static int virtio_gpu_init(struct driver *drv)
{
int ret;
struct virtio_gpu_priv *priv;
struct drm_virtgpu_getparam args;
priv = calloc(1, sizeof(*priv));
drv->priv = priv;
for (uint32_t i = 0; i < ARRAY_SIZE(features); i++) {
struct drm_virtgpu_getparam params = { 0 };
memset(&args, 0, sizeof(args));
args.param = VIRTGPU_PARAM_3D_FEATURES;
args.value = (uint64_t)(uintptr_t)&priv->has_3d;
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &args);
if (ret) {
drv_log("virtio 3D acceleration is not available\n");
/* Be paranoid */
priv->has_3d = 0;
params.param = features[i].feature;
params.value = (uint64_t)(uintptr_t)&features[i].enabled;
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &params);
if (ret)
drv_log("DRM_IOCTL_VIRTGPU_GET_PARAM failed with %s\n", strerror(errno));
}
if (priv->has_3d) {
if (features[feat_3d].enabled) {
virtio_gpu_get_caps(drv, &priv->caps, &priv->caps_is_v2);
/* This doesn't mean host can scanout everything, it just means host
@ -337,7 +345,7 @@ static int virtio_gpu_init(struct driver *drv)
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
BO_USE_HW_VIDEO_ENCODER);
drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER);
return drv_modify_linear_combinations(drv);
}
@ -351,8 +359,7 @@ static void virtio_gpu_close(struct driver *drv)
static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
uint64_t use_flags)
{
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
if (priv->has_3d)
if (features[feat_3d].enabled)
return virtio_virgl_bo_create(bo, width, height, format, use_flags);
else
return virtio_dumb_bo_create(bo, width, height, format, use_flags);
@ -360,8 +367,7 @@ static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height,
static int virtio_gpu_bo_destroy(struct bo *bo)
{
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
if (priv->has_3d)
if (features[feat_3d].enabled)
return drv_gem_bo_destroy(bo);
else
return drv_dumb_bo_destroy(bo);
@ -369,8 +375,7 @@ static int virtio_gpu_bo_destroy(struct bo *bo)
static void *virtio_gpu_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
{
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
if (priv->has_3d)
if (features[feat_3d].enabled)
return virtio_virgl_bo_map(bo, vma, plane, map_flags);
else
return drv_dumb_bo_map(bo, vma, plane, map_flags);
@ -380,10 +385,9 @@ static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
{
int ret;
struct drm_virtgpu_3d_transfer_from_host xfer;
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
struct drm_virtgpu_3d_wait waitcmd;
if (!priv->has_3d)
if (!features[feat_3d].enabled)
return 0;
// Invalidate is only necessary if the host writes to the buffer.
@ -434,10 +438,9 @@ static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping)
{
int ret;
struct drm_virtgpu_3d_transfer_to_host xfer;
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
struct drm_virtgpu_3d_wait waitcmd;
if (!priv->has_3d)
if (!features[feat_3d].enabled)
return 0;
if (!(mapping->vma->map_flags & BO_MAP_WRITE))
@ -482,7 +485,6 @@ static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping)
static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
{
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
switch (format) {
case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
@ -496,7 +498,7 @@ static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, u
* All of our host drivers prefer NV12 as their flexible media format.
* If that changes, this will need to be modified.
*/
if (priv->has_3d)
if (features[feat_3d].enabled)
return DRM_FORMAT_NV12;
else
return DRM_FORMAT_YVU420;
@ -505,6 +507,37 @@ static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, u
}
}
static int virtio_gpu_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
uint32_t offsets[DRV_MAX_PLANES])
{
int ret;
struct drm_virtgpu_resource_info res_info;
if (!features[feat_3d].enabled)
return 0;
memset(&res_info, 0, sizeof(res_info));
res_info.bo_handle = bo->handles[0].u32;
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, &res_info);
if (ret) {
drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed with %s\n", strerror(errno));
return ret;
}
for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
/*
* Currently, kernel v4.14 (Betty) doesn't have the extended resource info
* ioctl.
*/
if (res_info.strides[plane]) {
strides[plane] = res_info.strides[plane];
offsets[plane] = res_info.offsets[plane];
}
}
return 0;
}
const struct backend backend_virtio_gpu = {
.name = "virtio_gpu",
.init = virtio_gpu_init,
@ -517,4 +550,5 @@ const struct backend backend_virtio_gpu = {
.bo_invalidate = virtio_gpu_bo_invalidate,
.bo_flush = virtio_gpu_bo_flush,
.resolve_format = virtio_gpu_resolve_format,
.resource_info = virtio_gpu_resource_info,
};