From 31dcb39615a5d1541a7e5b27e19566b48aac381d Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Mon, 2 May 2022 09:25:56 -0700 Subject: [PATCH] gallium/vl: Add software winsys and offscreen winsys Acked-by: Jesse Natalie Part-of: --- src/gallium/auxiliary/meson.build | 6 + src/gallium/auxiliary/vl/vl_winsys.h | 12 ++ src/gallium/auxiliary/vl/vl_winsys_dri_vgem.c | 68 ++++++++ src/gallium/auxiliary/vl/vl_winsys_xlib_swrast.c | 199 +++++++++++++++++++++++ src/gallium/frontends/va/context.c | 13 +- src/gallium/frontends/vdpau/device.c | 2 + src/gallium/targets/va/meson.build | 14 +- src/gallium/targets/vdpau/meson.build | 13 +- 8 files changed, 317 insertions(+), 10 deletions(-) create mode 100644 src/gallium/auxiliary/vl/vl_winsys_dri_vgem.c create mode 100644 src/gallium/auxiliary/vl/vl_winsys_xlib_swrast.c diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build index 5d23c78..2f1fc11 100644 --- a/src/gallium/auxiliary/meson.build +++ b/src/gallium/auxiliary/meson.build @@ -475,6 +475,12 @@ if with_dri2 and with_platform_x11 endif endif +if with_glx == 'xlib' or with_glx == 'gallium-xlib' + files_libgalliumvlwinsys += files('vl/vl_winsys_xlib_swrast.c') +else + files_libgalliumvlwinsys += files('vl/vl_winsys_dri_vgem.c') +endif + prog_enums2names = files('driver_trace/enums2names.py') files_libgallium += custom_target( 'tr_util.[ch]', diff --git a/src/gallium/auxiliary/vl/vl_winsys.h b/src/gallium/auxiliary/vl/vl_winsys.h index a12b08b..387bc42 100644 --- a/src/gallium/auxiliary/vl/vl_winsys.h +++ b/src/gallium/auxiliary/vl/vl_winsys.h @@ -96,4 +96,16 @@ vl_dri3_screen_create(void *display, int screen) { return NULL; }; struct vl_screen * vl_drm_screen_create(int fd); +#ifdef USE_XSHM +struct vl_screen * +vl_xlib_swrast_screen_create(Display *display, int screen); +static inline struct vl_screen * +vl_vgem_drm_screen_create(int fd) { return NULL; } +#else +struct vl_screen * +vl_vgem_drm_screen_create(int fd); +static inline struct vl_screen * +vl_xlib_swrast_screen_create(Display *display, int screen) { return NULL; } +#endif + #endif diff --git a/src/gallium/auxiliary/vl/vl_winsys_dri_vgem.c b/src/gallium/auxiliary/vl/vl_winsys_dri_vgem.c new file mode 100644 index 0000000..317cbd8 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_winsys_dri_vgem.c @@ -0,0 +1,68 @@ +/* + * Copyright © Microsoft Corporation + * + * 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 OR COPYRIGHT HOLDERS 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. + */ + +#include "pipe/p_screen.h" + +#include "util/u_memory.h" +#include "vl/vl_winsys.h" + +#include "target-helpers/sw_helper_public.h" +#include "gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.h" + +static void +vl_vgem_drm_screen_destroy(struct vl_screen *vscreen) +{ + if (vscreen) { + if (vscreen->pscreen) + vscreen->pscreen->destroy(vscreen->pscreen); + FREE(vscreen); + } +} + +struct vl_screen * +vl_vgem_drm_screen_create(int fd) +{ + struct vl_screen *vscreen = CALLOC_STRUCT(vl_screen); + if (!vscreen) + return NULL; + + struct sw_winsys *winsys = kms_dri_create_winsys(fd); + if (winsys == NULL) + goto release_pipe; + + vscreen->pscreen = sw_screen_create(winsys); + if (!vscreen->pscreen) + goto release_pipe; + + vscreen->destroy = vl_vgem_drm_screen_destroy; + vscreen->texture_from_drawable = NULL; + vscreen->get_dirty_area = NULL; + vscreen->get_timestamp = NULL; + vscreen->set_next_timestamp = NULL; + vscreen->get_private = NULL; + return vscreen; + +release_pipe: + vl_vgem_drm_screen_destroy(vscreen); + return NULL; +} diff --git a/src/gallium/auxiliary/vl/vl_winsys_xlib_swrast.c b/src/gallium/auxiliary/vl/vl_winsys_xlib_swrast.c new file mode 100644 index 0000000..1d3b4a8 --- /dev/null +++ b/src/gallium/auxiliary/vl/vl_winsys_xlib_swrast.c @@ -0,0 +1,199 @@ +/* + * Copyright © Microsoft Corporation + * + * 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 OR COPYRIGHT HOLDERS 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. + */ + +#include "pipe-loader/pipe_loader.h" +#include "pipe/p_screen.h" + +#include "util/u_memory.h" +#include "vl/vl_winsys.h" +#include +#include + +#include "gallium/include/frontend/xlibsw_api.h" +#include "gallium/winsys/sw/xlib/xlib_sw_winsys.h" +#include "loader.h" +#include "target-helpers/sw_helper_public.h" +#include "vl/vl_compositor.h" + +struct vl_xlib_screen +{ + struct vl_screen base; + struct pipe_context *pipe; + Display *display; + int screen; + struct u_rect dirty_area; + XVisualInfo xlib_drawable_visual_info; + struct xlib_drawable xlib_drawable_handle; + struct pipe_resource *drawable_texture; +}; + +static void +vl_screen_destroy(struct vl_screen *vscreen) +{ + if (vscreen == NULL) + return; + + if (vscreen->pscreen) + vscreen->pscreen->destroy(vscreen->pscreen); + + if (vscreen->dev) + pipe_loader_release(&vscreen->dev, 1); + + FREE(vscreen); +} + +struct pipe_resource * +vl_swrast_texture_from_drawable(struct vl_screen *vscreen, void *drawable); + +struct u_rect * +vl_swrast_get_dirty_area(struct vl_screen *vscreen); + +void * +vl_swrast_get_private(struct vl_screen *vscreen); + +static void +vl_xlib_screen_destroy(struct vl_screen *vscreen) +{ + if (vscreen == NULL) + return; + + struct vl_xlib_screen *xlib_screen = (struct vl_xlib_screen *) vscreen; + + if (xlib_screen->drawable_texture) + pipe_resource_reference(&xlib_screen->drawable_texture, NULL); + + if (xlib_screen->pipe) + xlib_screen->pipe->destroy(xlib_screen->pipe); + + vl_screen_destroy(&xlib_screen->base); +} + +struct vl_screen * +vl_xlib_swrast_screen_create(Display *display, int screen) +{ + struct vl_xlib_screen *vscreen = CALLOC_STRUCT(vl_xlib_screen); + if (!vscreen) + goto handle_err_xlib_swrast_create; + + struct sw_winsys *xlib_winsys = xlib_create_sw_winsys(display); + if (xlib_winsys == NULL) + goto handle_err_xlib_swrast_create; + + vscreen->base.pscreen = sw_screen_create(xlib_winsys); + if (!vscreen->base.pscreen) + goto handle_err_xlib_swrast_create; + + vscreen->base.get_private = vl_swrast_get_private; + vscreen->base.texture_from_drawable = vl_swrast_texture_from_drawable; + vscreen->base.get_dirty_area = vl_swrast_get_dirty_area; + vscreen->base.destroy = vl_xlib_screen_destroy; + vscreen->pipe = vscreen->base.pscreen->context_create(vscreen->base.pscreen, NULL, 0); + + vl_compositor_reset_dirty_area(&vscreen->dirty_area); + vscreen->display = display; + vscreen->screen = screen; + + return &vscreen->base; + +handle_err_xlib_swrast_create: + if (vscreen) + vl_xlib_screen_destroy(&vscreen->base); + + return NULL; +} + +void +vl_swrast_fill_xlib_drawable_desc(struct vl_screen *vscreen, + Window x11_window, + struct xlib_drawable *drawable_desc); + +void +vl_swrast_fill_xlib_drawable_desc(struct vl_screen *vscreen, + Window x11_window, + struct xlib_drawable *drawable_desc) +{ + struct vl_xlib_screen *scrn = (struct vl_xlib_screen *) vscreen; + XWindowAttributes x11_window_attrs = {}; + XGetWindowAttributes(scrn->display, x11_window, &x11_window_attrs); + XMatchVisualInfo(scrn->display, scrn->screen, x11_window_attrs.depth, TrueColor, &scrn->xlib_drawable_visual_info); + scrn->xlib_drawable_handle.depth = x11_window_attrs.depth; + scrn->xlib_drawable_handle.drawable = x11_window; + scrn->xlib_drawable_handle.visual = scrn->xlib_drawable_visual_info.visual; +} + +struct pipe_resource * +vl_swrast_texture_from_drawable(struct vl_screen *vscreen, void *drawable) +{ + struct vl_xlib_screen *scrn = (struct vl_xlib_screen *) vscreen; + Window x11_window = (Window) drawable; + vl_swrast_fill_xlib_drawable_desc(vscreen, x11_window, &scrn->xlib_drawable_handle); + + XWindowAttributes x11_window_attrs = {}; + XGetWindowAttributes(scrn->display, x11_window, &x11_window_attrs); + enum pipe_format x11_window_format = vl_dri2_format_for_depth(&scrn->base, x11_window_attrs.depth); + + bool needs_new_back_buffer_allocation = true; + if (scrn->drawable_texture) { + needs_new_back_buffer_allocation = + (scrn->drawable_texture->width0 != x11_window_attrs.width || scrn->drawable_texture->height0 != x11_window_attrs.height || + scrn->drawable_texture->format != x11_window_format); + } + + if (needs_new_back_buffer_allocation) { + if (scrn->drawable_texture) + pipe_resource_reference(&scrn->drawable_texture, NULL); + + struct pipe_resource templat; + memset(&templat, 0, sizeof(templat)); + templat.target = PIPE_TEXTURE_2D; + templat.format = x11_window_format; + templat.width0 = x11_window_attrs.width; + templat.height0 = x11_window_attrs.height; + templat.depth0 = 1; + templat.array_size = 1; + templat.last_level = 0; + templat.bind = (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET); + + scrn->drawable_texture = vscreen->pscreen->resource_create(vscreen->pscreen, &templat); + } else { + struct pipe_resource *drawable_texture = NULL; + pipe_resource_reference(&drawable_texture, scrn->drawable_texture); + } + + return scrn->drawable_texture; +} + +void * +vl_swrast_get_private(struct vl_screen *vscreen) +{ + struct vl_xlib_screen *scrn = (struct vl_xlib_screen *) vscreen; + return &scrn->xlib_drawable_handle; +} + +struct u_rect * +vl_swrast_get_dirty_area(struct vl_screen *vscreen) +{ + struct vl_xlib_screen *scrn = (struct vl_xlib_screen *) vscreen; + vl_compositor_reset_dirty_area(&scrn->dirty_area); + return &scrn->dirty_area; +} diff --git a/src/gallium/frontends/va/context.c b/src/gallium/frontends/va/context.c index 665187c..ad82d39 100644 --- a/src/gallium/frontends/va/context.c +++ b/src/gallium/frontends/va/context.c @@ -35,6 +35,7 @@ #include "vl/vl_winsys.h" #include "va_private.h" +#include "loader/loader.h" #include @@ -129,6 +130,8 @@ VA_DRIVER_INIT_FUNC(VADriverContextP ctx) drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen); if (!drv->vscreen) drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen); + if (!drv->vscreen) + drv->vscreen = vl_xlib_swrast_screen_create(ctx->native_dpy, ctx->x11_screen); break; case VA_DISPLAY_WAYLAND: case VA_DISPLAY_DRM: @@ -139,8 +142,14 @@ VA_DRIVER_INIT_FUNC(VADriverContextP ctx) FREE(drv); return VA_STATUS_ERROR_INVALID_PARAMETER; } - - drv->vscreen = vl_drm_screen_create(drm_info->fd); + char* drm_driver_name = loader_get_driver_for_fd(drm_info->fd); + if(drm_driver_name) { + if (strcmp(drm_driver_name, "vgem") == 0) + drv->vscreen = vl_vgem_drm_screen_create(drm_info->fd); + FREE(drm_driver_name); + } + if(!drv->vscreen) + drv->vscreen = vl_drm_screen_create(drm_info->fd); break; } default: diff --git a/src/gallium/frontends/vdpau/device.c b/src/gallium/frontends/vdpau/device.c index f69c54c..baffa5d 100644 --- a/src/gallium/frontends/vdpau/device.c +++ b/src/gallium/frontends/vdpau/device.c @@ -66,6 +66,8 @@ vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, dev->vscreen = vl_dri3_screen_create(display, screen); if (!dev->vscreen) dev->vscreen = vl_dri2_screen_create(display, screen); + if (!dev->vscreen) + dev->vscreen = vl_xlib_swrast_screen_create(display, screen); if (!dev->vscreen) { ret = VDP_STATUS_RESOURCES; goto no_vscreen; diff --git a/src/gallium/targets/va/meson.build b/src/gallium/targets/va/meson.build index 8cbddc3..0465e87 100644 --- a/src/gallium/targets/va/meson.build +++ b/src/gallium/targets/va/meson.build @@ -31,6 +31,15 @@ if with_ld_version_script va_link_depends += files('va.sym') endif +link_with_libva_gallium = [ + libgalliumvlwinsys, libgalliumvl, libgallium, + libpipe_loader_static, libws_null, libwsw, libswdri, libswkmsdri, +] + +if with_glx == 'xlib' or with_glx == 'gallium-xlib' + link_with_libva_gallium += [libws_xlib] +endif + libva_gallium = shared_library( 'gallium_drv_video', 'target.c', @@ -40,10 +49,7 @@ libva_gallium = shared_library( inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_util, inc_gallium_winsys, inc_gallium_drivers, ], link_whole : [libva_st], - link_with : [ - libgalliumvlwinsys, libgalliumvl, libgallium, - libpipe_loader_static, libws_null, libwsw, libswdri, libswkmsdri, - ], + link_with : link_with_libva_gallium, dependencies : [ dep_libdrm, driver_r600, driver_radeonsi, driver_nouveau, idep_mesautil, diff --git a/src/gallium/targets/vdpau/meson.build b/src/gallium/targets/vdpau/meson.build index 6c726a2..d994b46 100644 --- a/src/gallium/targets/vdpau/meson.build +++ b/src/gallium/targets/vdpau/meson.build @@ -35,6 +35,14 @@ if with_ld_dynamic_list vdpau_link_depends += files('../dri-vdpau.dyn') endif +link_with_libvdpau_gallium = [ + libgalliumvlwinsys, libgalliumvl, libgallium, + libpipe_loader_static, libws_null, libwsw, libswdri, libswkmsdri, +] + +if with_glx == 'xlib' or with_glx == 'gallium-xlib' + link_with_libvdpau_gallium += [libws_xlib] +endif libvdpau_gallium = shared_library( 'vdpau_gallium', @@ -45,10 +53,7 @@ libvdpau_gallium = shared_library( inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_util, inc_gallium_winsys, inc_gallium_drivers, ], link_whole : [libvdpau_st], - link_with : [ - libgalliumvlwinsys, libgalliumvl, libgallium, - libpipe_loader_static, libws_null, libwsw, libswdri, libswkmsdri, - ], + link_with : link_with_libvdpau_gallium, dependencies : [ idep_mesautil, driver_r300, driver_r600, driver_radeonsi, driver_nouveau, -- 2.7.4