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:
commit
01b2926cf7
25 changed files with 743 additions and 169 deletions
12
OWNERS
12
OWNERS
|
|
@ -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
2
OWNERS.android
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
adelva@google.com
|
||||
natsu@google.com
|
||||
108
amdgpu.c
108
amdgpu.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 &);
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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 &);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
257
dri.c
|
|
@ -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
3
dri.h
|
|
@ -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
27
drv.c
|
|
@ -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
5
drv.h
|
|
@ -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__); \
|
||||
|
|
|
|||
|
|
@ -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
6
gbm.c
|
|
@ -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;
|
||||
|
|
|
|||
27
helpers.c
27
helpers.c
|
|
@ -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
4
i915.c
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
8
meson.c
8
meson.c
|
|
@ -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
2
msm.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
39
synaptics.c
Normal 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
40
vc4.c
|
|
@ -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
188
virtgpu_drm.h
Normal 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
|
||||
108
virtio_gpu.c
108
virtio_gpu.c
|
|
@ -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(¶m_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, ¶m_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, ¶ms);
|
||||
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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue