@ -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 )
{