diff options
Diffstat (limited to 'src/vrend_winsys_egl.c')
-rw-r--r-- | src/vrend_winsys_egl.c | 176 |
1 files changed, 102 insertions, 74 deletions
diff --git a/src/vrend_winsys_egl.c b/src/vrend_winsys_egl.c index 6a6e7f77..de116d5a 100644 --- a/src/vrend_winsys_egl.c +++ b/src/vrend_winsys_egl.c @@ -39,6 +39,7 @@ #include "util/u_memory.h" #include "virglrenderer.h" +#include "vrend_winsys.h" #include "vrend_winsys_egl.h" #include "virgl_hw.h" #include "vrend_winsys_gbm.h" @@ -405,121 +406,148 @@ bool virgl_has_egl_khr_gl_colorspace(struct virgl_egl *egl) return has_bit(egl->extension_bits, EGL_KHR_GL_COLORSPACE); } +void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, + uint32_t width, + uint32_t height, + uint32_t drm_format, + uint64_t drm_modifier, + uint32_t plane_count, + const int *plane_fds, + const uint32_t *plane_strides, + const uint32_t *plane_offsets) +{ + EGLint attrs[6 + VIRGL_GBM_MAX_PLANES * 10 + 1]; + uint32_t count; + + assert(VIRGL_GBM_MAX_PLANES <= 4); + assert(plane_count && plane_count <= VIRGL_GBM_MAX_PLANES); + + count = 0; + attrs[count++] = EGL_WIDTH; + attrs[count++] = width; + attrs[count++] = EGL_HEIGHT; + attrs[count++] = height; + attrs[count++] = EGL_LINUX_DRM_FOURCC_EXT; + attrs[count++] = drm_format; + for (uint32_t i = 0; i < plane_count; i++) { + if (i < 3) { + attrs[count++] = EGL_DMA_BUF_PLANE0_FD_EXT + i * 3; + attrs[count++] = plane_fds[i]; + attrs[count++] = EGL_DMA_BUF_PLANE0_PITCH_EXT + i * 3; + attrs[count++] = plane_strides[i]; + attrs[count++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT + i * 3; + attrs[count++] = plane_offsets[i]; + } + + if (has_bit(egl->extension_bits, EGL_EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS)) { + if (i == 3) { + attrs[count++] = EGL_DMA_BUF_PLANE3_FD_EXT; + attrs[count++] = plane_fds[i]; + attrs[count++] = EGL_DMA_BUF_PLANE3_PITCH_EXT; + attrs[count++] = plane_strides[i]; + attrs[count++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT; + attrs[count++] = plane_offsets[i]; + } + + if (drm_modifier != DRM_FORMAT_MOD_INVALID) { + attrs[count++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT + i * 2; + attrs[count++] = (uint32_t)drm_modifier; + attrs[count++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT + i * 2; + attrs[count++] = (uint32_t)(drm_modifier >> 32); + } + } + } + attrs[count++] = EGL_NONE; + assert(count <= ARRAY_SIZE(attrs)); + + return (void *)eglCreateImageKHR(egl->egl_display, + EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + (EGLClientBuffer)NULL, + attrs); +} + +void virgl_egl_image_destroy(struct virgl_egl *egl, void *image) +{ + eglDestroyImageKHR(egl->egl_display, image); +} + #ifdef ENABLE_MINIGBM_ALLOCATION -void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo) +void *virgl_egl_image_from_gbm_bo(struct virgl_egl *egl, struct gbm_bo *bo) { int ret; - EGLImageKHR image; + void *image = NULL; int fds[VIRGL_GBM_MAX_PLANES] = {-1, -1, -1, -1}; + uint32_t strides[VIRGL_GBM_MAX_PLANES]; + uint32_t offsets[VIRGL_GBM_MAX_PLANES]; 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] = { - EGL_WIDTH, - gbm_bo_get_width(bo), - EGL_HEIGHT, - gbm_bo_get_height(bo), - EGL_LINUX_DRM_FOURCC_EXT, - (int)gbm_bo_get_format(bo), - EGL_NONE, - }; if (num_planes < 0 || num_planes > VIRGL_GBM_MAX_PLANES) - return (void *)EGL_NO_IMAGE_KHR; + return NULL; for (int plane = 0; plane < num_planes; plane++) { uint32_t handle = gbm_bo_get_handle_for_plane(bo, plane).u32; ret = virgl_gbm_export_fd(egl->gbm->device, handle, &fds[plane]); if (ret < 0) { vrend_printf( "failed to export plane handle\n"); - image = (void *)EGL_NO_IMAGE_KHR; goto out_close; } - } - size_t attrs_index = 6; - for (int plane = 0; plane < num_planes; plane++) { - khr_image_attrs[attrs_index++] = EGL_DMA_BUF_PLANE0_FD_EXT + plane * 3; - khr_image_attrs[attrs_index++] = fds[plane]; - khr_image_attrs[attrs_index++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT + plane * 3; - khr_image_attrs[attrs_index++] = gbm_bo_get_offset(bo, plane); - khr_image_attrs[attrs_index++] = EGL_DMA_BUF_PLANE0_PITCH_EXT + plane * 3; - khr_image_attrs[attrs_index++] = gbm_bo_get_stride_for_plane(bo, plane); - if (has_bit(egl->extension_bits, EGL_EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS)) { - const uint64_t modifier = gbm_bo_get_modifier(bo); - khr_image_attrs[attrs_index++] = - EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT + plane * 2; - khr_image_attrs[attrs_index++] = modifier & 0xfffffffful; - khr_image_attrs[attrs_index++] = - EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT + plane * 2; - khr_image_attrs[attrs_index++] = modifier >> 32; - } + strides[plane] = gbm_bo_get_stride_for_plane(bo, plane); + offsets[plane] = gbm_bo_get_offset(bo, plane); } - khr_image_attrs[attrs_index++] = EGL_NONE; - image = eglCreateImageKHR(egl->egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, - khr_image_attrs); + image = virgl_egl_image_from_dmabuf(egl, + gbm_bo_get_width(bo), + gbm_bo_get_height(bo), + gbm_bo_get_format(bo), + gbm_bo_get_modifier(bo), + num_planes, + fds, + strides, + offsets); out_close: for (int plane = 0; plane < num_planes; plane++) close(fds[plane]); - return (void*)image; + return image; } -void *virgl_egl_aux_plane_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo, int plane) +void *virgl_egl_aux_plane_image_from_gbm_bo(struct virgl_egl *egl, struct gbm_bo *bo, int plane) { int ret; - EGLImageKHR image = EGL_NO_IMAGE_KHR; + void *image = NULL; 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; + return NULL; 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 (has_bit(egl->extension_bits, EGL_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; + return NULL; } - image = eglCreateImageKHR(egl->egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, khr_image_attrs); - + const uint32_t format = bytes_per_pixel == 1 ? GBM_FORMAT_R8 : GBM_FORMAT_GR88; + const uint32_t stride = gbm_bo_get_stride_for_plane(bo, plane); + const uint32_t offset = gbm_bo_get_offset(bo, plane); + image = virgl_egl_image_from_dmabuf(egl, + virgl_gbm_get_plane_width(bo, plane), + virgl_gbm_get_plane_height(bo, plane), + format, + gbm_bo_get_modifier(bo), + 1, + &fd, + &stride, + &offset); close(fd); - return (void*)image; -} -void virgl_egl_image_destroy(struct virgl_egl *egl, void *image) -{ - eglDestroyImageKHR(egl->egl_display, image); + return image; } -#endif +#endif /* ENABLE_MINIGBM_ALLOCATION */ bool virgl_egl_supports_fences(struct virgl_egl *egl) { |