vrend: support emulating planar image sampling

Mesa emulates planar format sampling with per-plane samplers. With this
change, the guest can pass the plane index when creating a sampler view
from a virgl resource to create a per-plane sampler view. The index can
be passed in place of the texture layer, as that will always be 0 for
planar images.

Signed-off-by: David Stevens <stevensd@chromium.org>
Reviewed-by: Lepton Wu <lepton@chromium.org>
macos/master
David Stevens 5 years ago committed by Lepton Wu
parent cf423460fd
commit 77d2681823
  1. 1
      src/virgl_egl.h
  2. 53
      src/virgl_egl_context.c
  3. 38
      src/virgl_gbm.c
  4. 10
      src/virgl_gbm.h
  5. 24
      src/vrend_renderer.c
  6. 2
      src/vrend_renderer.h

@ -54,5 +54,6 @@ int virgl_egl_get_fd_for_texture2(struct virgl_egl *egl, uint32_t tex_id, int *f
int *offset);
void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo);
void *virgl_egl_aux_plane_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo, int plane);
void virgl_egl_image_destroy(struct virgl_egl *egl, void *image);
#endif

@ -381,7 +381,7 @@ void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo)
{
int ret;
EGLImageKHR image;
int fds[4] = {-1, -1, -1, -1};
int fds[VIRGL_GBM_MAX_PLANES] = {-1, -1, -1, -1};
int num_planes = gbm_bo_get_plane_count(bo);
// When the bo has 3 planes with modifier support, it requires 37 components.
EGLint khr_image_attrs[37] = {
@ -394,7 +394,7 @@ void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo)
EGL_NONE,
};
if (num_planes < 0 || num_planes > 4)
if (num_planes < 0 || num_planes > VIRGL_GBM_MAX_PLANES)
return (void *)EGL_NO_IMAGE_KHR;
for (int plane = 0; plane < num_planes; plane++) {
@ -437,6 +437,55 @@ out_close:
return (void*)image;
}
void *virgl_egl_aux_plane_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo, int plane)
{
int ret;
EGLImageKHR image = EGL_NO_IMAGE_KHR;
int fd = -1;
int bytes_per_pixel = virgl_gbm_get_plane_bytes_per_pixel(bo, plane);
if (bytes_per_pixel != 1 && bytes_per_pixel != 2)
return (void *)EGL_NO_IMAGE_KHR;
uint32_t handle = gbm_bo_get_handle_for_plane(bo, plane).u32;
ret = drmPrimeHandleToFD(gbm_device_get_fd(egl->gbm->device), handle, DRM_CLOEXEC, &fd);
if (ret < 0) {
vrend_printf("failed to export plane handle %d\n", errno);
return (void *)EGL_NO_IMAGE_KHR;
}
EGLint khr_image_attrs[17] = {
EGL_WIDTH,
virgl_gbm_get_plane_width(bo, plane),
EGL_HEIGHT,
virgl_gbm_get_plane_height(bo, plane),
EGL_LINUX_DRM_FOURCC_EXT,
(int) (bytes_per_pixel == 1 ? GBM_FORMAT_R8 : GBM_FORMAT_GR88),
EGL_DMA_BUF_PLANE0_FD_EXT,
fd,
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
gbm_bo_get_offset(bo, plane),
EGL_DMA_BUF_PLANE0_PITCH_EXT,
gbm_bo_get_stride_for_plane(bo, plane),
};
if (egl->have_ext_image_dma_buf_import_modifiers) {
const uint64_t modifier = gbm_bo_get_modifier(bo);
khr_image_attrs[12] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
khr_image_attrs[13] = modifier & 0xfffffffful;
khr_image_attrs[14] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
khr_image_attrs[15] = modifier >> 32;
khr_image_attrs[16] = EGL_NONE;
} else {
khr_image_attrs[12] = EGL_NONE;
}
image = eglCreateImageKHR(egl->egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, khr_image_attrs);
close(fd);
return (void*)image;
}
void virgl_egl_image_destroy(struct virgl_egl *egl, void *image)
{
eglDestroyImageKHR(egl->egl_display, image);

@ -44,9 +44,9 @@
struct planar_layout {
size_t num_planes;
int horizontal_subsampling[4];
int vertical_subsampling[4];
int bytes_per_pixel[4];
int horizontal_subsampling[VIRGL_GBM_MAX_PLANES];
int vertical_subsampling[VIRGL_GBM_MAX_PLANES];
int bytes_per_pixel[VIRGL_GBM_MAX_PLANES];
};
struct format_conversion {
@ -404,16 +404,16 @@ int virgl_gbm_export_fd(struct gbm_device *gbm, uint32_t handle, int32_t *out_fd
int virgl_gbm_export_query(struct gbm_bo *bo, struct virgl_renderer_export_query *query)
{
int ret = -1;
uint32_t handles[4] = {0, 0, 0, 0};
uint32_t handles[VIRGL_GBM_MAX_PLANES] = { 0 };
struct gbm_device *gbm = gbm_bo_get_device(bo);
int num_planes = gbm_bo_get_plane_count(bo);
if (num_planes < 0 || num_planes > 4)
if (num_planes < 0 || num_planes > VIRGL_GBM_MAX_PLANES)
return ret;
query->out_num_fds = 0;
query->out_fourcc = 0;
query->out_modifier = 0;
for (int plane = 0; plane < 4; plane++) {
for (int plane = 0; plane < VIRGL_GBM_MAX_PLANES; plane++) {
query->out_fds[plane] = -1;
query->out_strides[plane] = 0;
query->out_offsets[plane] = 0;
@ -446,7 +446,7 @@ int virgl_gbm_export_query(struct gbm_bo *bo, struct virgl_renderer_export_query
return 0;
err_close:
for (int plane = 0; plane < 4; plane++) {
for (int plane = 0; plane < VIRGL_GBM_MAX_PLANES; plane++) {
if (query->out_fds[plane] >= 0) {
close(query->out_fds[plane]);
query->out_fds[plane] = -1;
@ -459,3 +459,27 @@ err_close:
query->out_num_fds = 0;
return ret;
}
int virgl_gbm_get_plane_width(struct gbm_bo *bo, int plane) {
uint32_t format = gbm_bo_get_format(bo);
const struct planar_layout *layout = layout_from_format(format);
if (!layout)
return -1;
return gbm_bo_get_width(bo) / layout->horizontal_subsampling[plane];
}
int virgl_gbm_get_plane_height(struct gbm_bo *bo, int plane) {
uint32_t format = gbm_bo_get_format(bo);
const struct planar_layout *layout = layout_from_format(format);
if (!layout)
return -1;
return gbm_bo_get_height(bo) / layout->vertical_subsampling[plane];
}
int virgl_gbm_get_plane_bytes_per_pixel(struct gbm_bo *bo, int plane) {
uint32_t format = gbm_bo_get_format(bo);
const struct planar_layout *layout = layout_from_format(format);
if (!layout)
return -1;
return layout->bytes_per_pixel[plane];
}

@ -29,6 +29,12 @@
#include "vrend_iov.h"
#include "virglrenderer.h"
#ifdef GBM_MAX_PLANES
#define VIRGL_GBM_MAX_PLANES GBM_MAX_PLANES
#else
#define VIRGL_GBM_MAX_PLANES 4
#endif
/*
* If fd >= 0, virglrenderer owns the fd since it was opened via a rendernode
* query. If fd < 0, the gbm device was opened with the fd provided by the
@ -54,4 +60,8 @@ int virgl_gbm_export_fd(struct gbm_device *gbm, uint32_t handle, int32_t *out_fd
int virgl_gbm_export_query(struct gbm_bo *bo, struct virgl_renderer_export_query *query);
int virgl_gbm_get_plane_width(struct gbm_bo *bo, int plane);
int virgl_gbm_get_plane_height(struct gbm_bo *bo, int plane);
int virgl_gbm_get_plane_bytes_per_pixel(struct gbm_bo *bo, int plane);
#endif

@ -2125,6 +2125,13 @@ int vrend_create_sampler_view(struct vrend_context *ctx,
view->srgb_decode);
}
glBindTexture(view->target, 0);
} else if (needs_view && view->val0 && view->val0 <= ARRAY_SIZE(res->aux_plane_egl_image) &&
res->aux_plane_egl_image[view->val0 - 1]) {
void *image = res->aux_plane_egl_image[view->val0 - 1];
glGenTextures(1, &view->id);
glBindTexture(view->target, view->id);
glEGLImageTargetTexture2DOES(view->target, (GLeglImageOES) image);
glBindTexture(view->target, 0);
}
}
@ -6523,6 +6530,15 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr,
glBindTexture(gr->target, 0);
if (image_oes && gr->gbm_bo) {
#ifdef ENABLE_GBM_ALLOCATION
for (int i = 0; i < gbm_bo_get_plane_count(gr->gbm_bo) - 1; i++) {
gr->aux_plane_egl_image[i] =
virgl_egl_aux_plane_image_from_dmabuf(egl, gr->gbm_bo, i + 1);
}
#endif
}
gt->state.max_lod = -1;
gt->cur_swizzle_r = gt->cur_swizzle_g = gt->cur_swizzle_b = gt->cur_swizzle_a = -1;
gt->cur_base = -1;
@ -6648,8 +6664,14 @@ void vrend_renderer_resource_destroy(struct vrend_resource *res)
}
#ifdef ENABLE_GBM_ALLOCATION
if (res->egl_image)
if (res->egl_image) {
virgl_egl_image_destroy(egl, res->egl_image);
for (unsigned i = 0; i < ARRAY_SIZE(res->aux_plane_egl_image); i++) {
if (res->aux_plane_egl_image[i]) {
virgl_egl_image_destroy(egl, res->aux_plane_egl_image[i]);
}
}
}
if (res->gbm_bo)
gbm_bo_destroy(res->gbm_bo);
#endif

@ -31,6 +31,7 @@
#include "vrend_debug.h"
#include "vrend_tweaks.h"
#include "vrend_iov.h"
#include "virgl_gbm.h"
#include "virgl_hw.h"
#include <epoxy/gl.h>
@ -98,6 +99,7 @@ struct vrend_resource {
uint32_t num_iovs;
uint64_t mipmap_offsets[VR_MAX_TEXTURE_2D_LEVELS];
void *gbm_bo, *egl_image;
void *aux_plane_egl_image[VIRGL_GBM_MAX_PLANES - 1];
};
#define VIRGL_TEXTURE_NEED_SWIZZLE (1 << 0)

Loading…
Cancel
Save