diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2019-07-27 07:57:27 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2019-07-27 07:57:27 +0000 |
commit | d4a0bed4b91da9de86c311c7fef9a8aa9a6f500c (patch) | |
tree | a1b439049dee87bc951e190db93f5bbe8b43b0b5 /xserver/glamor | |
parent | b6bc775539a31f663f9e22ce3ccaf0aa96adf3b6 (diff) |
Update to xserver 1.20.5. Tested by jsg@
Diffstat (limited to 'xserver/glamor')
-rw-r--r-- | xserver/glamor/Makefile.am | 1 | ||||
-rw-r--r-- | xserver/glamor/Makefile.in | 15 | ||||
-rw-r--r-- | xserver/glamor/glamor.c | 177 | ||||
-rw-r--r-- | xserver/glamor/glamor.h | 108 | ||||
-rw-r--r-- | xserver/glamor/glamor_copy.c | 148 | ||||
-rw-r--r-- | xserver/glamor/glamor_core.c | 42 | ||||
-rw-r--r-- | xserver/glamor/glamor_debug.h | 29 | ||||
-rw-r--r-- | xserver/glamor/glamor_egl.c | 672 | ||||
-rw-r--r-- | xserver/glamor/glamor_egl.h | 1 | ||||
-rw-r--r-- | xserver/glamor/glamor_egl_ext.h | 65 | ||||
-rw-r--r-- | xserver/glamor/glamor_egl_stubs.c | 23 | ||||
-rw-r--r-- | xserver/glamor/glamor_eglmodule.c | 2 | ||||
-rw-r--r-- | xserver/glamor/glamor_fbo.c | 5 | ||||
-rw-r--r-- | xserver/glamor/glamor_gradient.c | 12 | ||||
-rw-r--r-- | xserver/glamor/glamor_image.c | 12 | ||||
-rw-r--r-- | xserver/glamor/glamor_priv.h | 39 | ||||
-rw-r--r-- | xserver/glamor/glamor_program.c | 7 | ||||
-rw-r--r-- | xserver/glamor/glamor_rects.c | 26 | ||||
-rw-r--r-- | xserver/glamor/glamor_render.c | 88 | ||||
-rw-r--r-- | xserver/glamor/glamor_transfer.c | 4 | ||||
-rw-r--r-- | xserver/glamor/glamor_utils.h | 64 | ||||
-rw-r--r-- | xserver/glamor/glamor_vbo.c | 15 | ||||
-rw-r--r-- | xserver/glamor/glamor_xv.c | 1 |
23 files changed, 991 insertions, 565 deletions
diff --git a/xserver/glamor/Makefile.am b/xserver/glamor/Makefile.am index 8c79994e0..aaf0aab17 100644 --- a/xserver/glamor/Makefile.am +++ b/xserver/glamor/Makefile.am @@ -56,6 +56,7 @@ endif libglamor_egl_stubs_la_SOURCES = \ glamor_egl_stubs.c \ + glamor_egl_ext.h \ glamor_egl.h sdk_HEADERS = glamor.h diff --git a/xserver/glamor/Makefile.in b/xserver/glamor/Makefile.in index aad01ca4c..21bdbc6e8 100644 --- a/xserver/glamor/Makefile.in +++ b/xserver/glamor/Makefile.in @@ -72,7 +72,7 @@ CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \ $(top_builddir)/include/xorg-config.h \ $(top_builddir)/include/xkb-config.h \ $(top_builddir)/include/xwin-config.h \ - $(top_builddir)/include/kdrive-config.h \ + $(top_builddir)/include/xwayland-config.h \ $(top_builddir)/include/version-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @@ -371,6 +371,7 @@ RANLIB = @RANLIB@ RAWCPP = @RAWCPP@ RAWCPPFLAGS = @RAWCPPFLAGS@ RELEASE_DATE = @RELEASE_DATE@ +SCANNER_ARG = @SCANNER_ARG@ SDK_REQUIRED_MODULES = @SDK_REQUIRED_MODULES@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ @@ -389,15 +390,18 @@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_DAEMON_CFLAGS = @SYSTEMD_DAEMON_CFLAGS@ SYSTEMD_DAEMON_LIBS = @SYSTEMD_DAEMON_LIBS@ TRADITIONALCPPFLAGS = @TRADITIONALCPPFLAGS@ -TSLIB_CFLAGS = @TSLIB_CFLAGS@ -TSLIB_LIBS = @TSLIB_LIBS@ UDEV_CFLAGS = @UDEV_CFLAGS@ UDEV_LIBS = @UDEV_LIBS@ UTILS_SYS_LIBS = @UTILS_SYS_LIBS@ VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ VERSION = @VERSION@ +WAYLAND_EGLSTREAM_CFLAGS = @WAYLAND_EGLSTREAM_CFLAGS@ +WAYLAND_EGLSTREAM_DATADIR = @WAYLAND_EGLSTREAM_DATADIR@ +WAYLAND_EGLSTREAM_LIBS = @WAYLAND_EGLSTREAM_LIBS@ WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ WAYLAND_SCANNER = @WAYLAND_SCANNER@ +WAYLAND_SCANNER_CFLAGS = @WAYLAND_SCANNER_CFLAGS@ +WAYLAND_SCANNER_LIBS = @WAYLAND_SCANNER_LIBS@ WINDOWSDRI_CFLAGS = @WINDOWSDRI_CFLAGS@ WINDOWSDRI_LIBS = @WINDOWSDRI_LIBS@ WINDOWSWM_CFLAGS = @WINDOWSWM_CFLAGS@ @@ -405,6 +409,8 @@ WINDOWSWM_LIBS = @WINDOWSWM_LIBS@ WINDRES = @WINDRES@ X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@ X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@ +XCONFIGDIR = @XCONFIGDIR@ +XCONFIGFILE = @XCONFIGFILE@ XDMCP_CFLAGS = @XDMCP_CFLAGS@ XDMCP_LIBS = @XDMCP_LIBS@ XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@ @@ -476,8 +482,6 @@ XWIN_SERVER_NAME = @XWIN_SERVER_NAME@ XWIN_SYS_LIBS = @XWIN_SYS_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ -__XCONFIGDIR__ = @__XCONFIGDIR__@ -__XCONFIGFILE__ = @__XCONFIGFILE__@ abi_ansic = @abi_ansic@ abi_extension = @abi_extension@ abi_videodrv = @abi_videodrv@ @@ -561,6 +565,7 @@ libglamor_la_SOURCES = glamor.c glamor_context.h glamor_copy.c \ glamor_sync.c glamor.h $(am__append_1) libglamor_egl_stubs_la_SOURCES = \ glamor_egl_stubs.c \ + glamor_egl_ext.h \ glamor_egl.h sdk_HEADERS = glamor.h diff --git a/xserver/glamor/glamor.c b/xserver/glamor/glamor.c index 2467443e0..b1c7d9f13 100644 --- a/xserver/glamor/glamor.c +++ b/xserver/glamor/glamor.c @@ -32,6 +32,7 @@ */ #include <stdlib.h> +#include <unistd.h> #include "glamor_priv.h" #include "mipict.h" @@ -40,6 +41,19 @@ DevPrivateKeyRec glamor_screen_private_key; DevPrivateKeyRec glamor_pixmap_private_key; DevPrivateKeyRec glamor_gc_private_key; +glamor_screen_private * +glamor_get_screen_private(ScreenPtr screen) +{ + return (glamor_screen_private *) + dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key); +} + +void +glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv) +{ + dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv); +} + /** * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable. * @@ -114,20 +128,6 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) glamor_pixmap_attach_fbo(pixmap, fbo); } -void -glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap) -{ - glamor_pixmap_private *pixmap_priv; - glamor_screen_private *glamor_priv; - - glamor_priv = glamor_get_screen_private(screen_pixmap->drawable.pScreen); - pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - glamor_priv->screen_fbo = pixmap_priv->fbo->fb; - - pixmap_priv->fbo->width = screen_pixmap->drawable.width; - pixmap_priv->fbo->height = screen_pixmap->drawable.height; -} - uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap) { @@ -136,6 +136,9 @@ glamor_get_pixmap_texture(PixmapPtr pixmap) if (!pixmap_priv) return 0; + if (!pixmap_priv->fbo) + return 0; + if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY) return 0; @@ -197,9 +200,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, w <= glamor_priv->glyph_max_dim && h <= glamor_priv->glyph_max_dim) || (w == 0 && h == 0) - || !glamor_check_pixmap_fbo_depth(depth)) - || (!GLAMOR_TEXTURED_LARGE_PIXMAP && - !glamor_check_fbo_size(glamor_priv, w, h))) + || !glamor_check_pixmap_fbo_depth(depth))) return fbCreatePixmap(screen, w, h, depth, usage); else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); @@ -349,25 +350,6 @@ fallback: } -/** - * Creates any pixmaps used internally by glamor, since those can't be - * allocated at ScreenInit time. - */ -static Bool -glamor_create_screen_resources(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - Bool ret = TRUE; - - screen->CreateScreenResources = - glamor_priv->saved_procs.create_screen_resources; - if (screen->CreateScreenResources) - ret = screen->CreateScreenResources(screen); - screen->CreateScreenResources = glamor_create_screen_resources; - - return ret; -} - static Bool glamor_check_instruction_count(int gl_version) { @@ -584,6 +566,14 @@ glamor_init(ScreenPtr screen, unsigned int flags) if (!glamor_check_instruction_count(gl_version)) goto fail; + + /* Glamor rendering assumes that platforms with GLSL 130+ + * have instanced arrays, but this is not always the case. + * etnaviv offers GLSL 140 with OpenGL 2.1. + */ + if (glamor_priv->glsl_version >= 130 && + !epoxy_has_gl_extension("GL_ARB_instanced_arrays")) + glamor_priv->glsl_version = 120; } else { if (gl_version < 20) { ErrorF("Require Open GLES2.0 or later.\n"); @@ -601,6 +591,12 @@ glamor_init(ScreenPtr screen, unsigned int flags) } } + if (!epoxy_has_gl_extension("GL_ARB_vertex_array_object") && + !epoxy_has_gl_extension("GL_OES_vertex_array_object")) { + ErrorF("GL_{ARB,OES}_vertex_array_object required\n"); + goto fail; + } + glamor_priv->has_rw_pbo = FALSE; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) glamor_priv->has_rw_pbo = TRUE; @@ -615,6 +611,8 @@ glamor_init(ScreenPtr screen, unsigned int flags) epoxy_has_gl_extension("GL_EXT_map_buffer_range"); glamor_priv->has_buffer_storage = epoxy_has_gl_extension("GL_ARB_buffer_storage"); + glamor_priv->has_mesa_tile_raster_order = + epoxy_has_gl_extension("GL_MESA_tile_raster_order"); glamor_priv->has_nv_texture_barrier = epoxy_has_gl_extension("GL_NV_texture_barrier"); glamor_priv->has_unpack_subimage = @@ -625,8 +623,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP || epoxy_gl_version() >= 30 || epoxy_has_gl_extension("GL_NV_pack_subimage"); - glamor_priv->has_vertex_array_object = - epoxy_has_gl_extension("GL_ARB_vertex_array_object"); glamor_priv->has_dual_blend = epoxy_has_gl_extension("GL_ARB_blend_func_extended"); @@ -666,10 +662,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_set_debug_level(&glamor_debug_level); - glamor_priv->saved_procs.create_screen_resources = - screen->CreateScreenResources; - screen->CreateScreenResources = glamor_create_screen_resources; - if (!glamor_font_init(screen)) goto fail; @@ -722,10 +714,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) ps->Glyphs = glamor_composite_glyphs; glamor_init_vbo(screen); - -#ifdef GLAMOR_GRADIENT_SHADER glamor_init_gradient_shader(screen); -#endif glamor_pixmap_init(screen); glamor_sync_init(screen); @@ -768,8 +757,6 @@ glamor_close_screen(ScreenPtr screen) glamor_sync_close(screen); glamor_composite_glyphs_fini(screen); screen->CloseScreen = glamor_priv->saved_procs.close_screen; - screen->CreateScreenResources = - glamor_priv->saved_procs.create_screen_resources; screen->CreateGC = glamor_priv->saved_procs.create_gc; screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; @@ -817,29 +804,91 @@ glamor_supports_pixmap_import_export(ScreenPtr screen) return glamor_priv->dri3_enabled; } -_X_EXPORT int -glamor_fd_from_pixmap(ScreenPtr screen, - PixmapPtr pixmap, CARD16 *stride, CARD32 *size) +_X_EXPORT void +glamor_set_drawable_modifiers_func(ScreenPtr screen, + GetDrawableModifiersFuncPtr func) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + glamor_priv->get_drawable_modifiers = func; +} + +_X_EXPORT Bool +glamor_get_drawable_modifiers(DrawablePtr draw, uint32_t format, + uint32_t *num_modifiers, uint64_t **modifiers) +{ + struct glamor_screen_private *glamor_priv = + glamor_get_screen_private(draw->pScreen); + + if (glamor_priv->get_drawable_modifiers) { + return glamor_priv->get_drawable_modifiers(draw, format, + num_modifiers, modifiers); + } + *num_modifiers = 0; + *modifiers = NULL; + return TRUE; +} + +static int +_glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *strides, uint32_t *offsets, + CARD32 *size, uint64_t *modifier) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); if (!glamor_priv->dri3_enabled) - return -1; + return 0; switch (pixmap_priv->type) { case GLAMOR_TEXTURE_DRM: case GLAMOR_TEXTURE_ONLY: - if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) - return -1; - return glamor_egl_dri3_fd_name_from_tex(screen, - pixmap, - pixmap_priv->fbo->tex, - FALSE, stride, size); + if (!glamor_pixmap_ensure_fbo(pixmap, pixmap->drawable.depth == 30 ? + GL_RGB10_A2 : GL_RGBA, 0)) + return 0; + + if (modifier) { + return glamor_egl_fds_from_pixmap(screen, pixmap, fds, + strides, offsets, + modifier); + } else { + CARD16 stride; + + fds[0] = glamor_egl_fd_from_pixmap(screen, pixmap, &stride, size); + strides[0] = stride; + + return fds[0] >= 0; + } default: break; } - return -1; + return 0; +} + +_X_EXPORT int +glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *strides, uint32_t *offsets, + uint64_t *modifier) +{ + return _glamor_fds_from_pixmap(screen, pixmap, fds, strides, offsets, + NULL, modifier); +} + +_X_EXPORT int +glamor_fd_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, CARD16 *stride, CARD32 *size) +{ + int fd; + int ret; + uint32_t stride32; + + ret = _glamor_fds_from_pixmap(screen, pixmap, &fd, &stride32, NULL, size, + NULL); + if (ret != 1) + return -1; + + *stride = stride32; + return fd; } _X_EXPORT int @@ -856,9 +905,10 @@ glamor_shareable_fd_from_pixmap(ScreenPtr screen, * 2 of those calls are also exported API, so we cannot just add a flag. */ pixmap->usage_hint = CREATE_PIXMAP_USAGE_SHARED; + ret = glamor_fd_from_pixmap(screen, pixmap, stride, size); - pixmap->usage_hint = orig_usage_hint; + pixmap->usage_hint = orig_usage_hint; return ret; } @@ -870,12 +920,11 @@ glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size) switch (pixmap_priv->type) { case GLAMOR_TEXTURE_DRM: case GLAMOR_TEXTURE_ONLY: - if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) + if (!glamor_pixmap_ensure_fbo(pixmap, pixmap->drawable.depth == 30 ? + GL_RGB10_A2 : GL_RGBA, 0)) return -1; - return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen, - pixmap, - pixmap_priv->fbo->tex, - TRUE, stride, size); + return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen, + pixmap, stride, size); default: break; } diff --git a/xserver/glamor/glamor.h b/xserver/glamor/glamor.h index bdd2374cf..09e9c895c 100644 --- a/xserver/glamor/glamor.h +++ b/xserver/glamor/glamor.h @@ -60,6 +60,11 @@ typedef enum glamor_pixmap_type { GLAMOR_TEXTURE_ONLY, } glamor_pixmap_type_t; +typedef Bool (*GetDrawableModifiersFuncPtr) (DrawablePtr draw, + uint32_t format, + uint32_t *num_modifiers, + uint64_t **modifiers); + #define GLAMOR_EGL_EXTERNAL_BUFFER 3 #define GLAMOR_USE_EGL_SCREEN (1 << 0) #define GLAMOR_NO_DRI3 (1 << 1) @@ -103,12 +108,6 @@ extern _X_EXPORT void glamor_fini(ScreenPtr screen); * Otherwise, the glamor internal structure will not be freed.*/ extern _X_EXPORT Bool glamor_close_screen(ScreenPtr screen); -/* Let glamor to know the screen's fbo. The low level - * driver should already assign a tex - * to this pixmap through the set_pixmap_texture. */ -extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap, - PixmapPtr *back_pixmap); - extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap); extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, @@ -142,17 +141,20 @@ extern _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, extern _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back); -/* The DDX is not supposed to call these three functions */ +/* The DDX is not supposed to call these four functions */ extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen); -extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr, - unsigned int, Bool, - CARD16 *, CARD32 *); +extern _X_EXPORT int glamor_egl_fds_from_pixmap(ScreenPtr, PixmapPtr, int *, + uint32_t *, uint32_t *, + uint64_t *); +extern _X_EXPORT int glamor_egl_fd_name_from_pixmap(ScreenPtr, PixmapPtr, + CARD16 *, CARD32 *); extern _X_EXPORT struct gbm_device *glamor_egl_get_gbm_device(ScreenPtr screen); +extern _X_EXPORT int glamor_egl_fd_from_pixmap(ScreenPtr, PixmapPtr, CARD16 *, CARD32 *); /* @glamor_supports_pixmap_import_export: Returns whether - * glamor_fd_from_pixmap(), glamor_name_from_pixmap(), and - * glamor_pixmap_from_fd() are supported. + * glamor_fds_from_pixmap(), glamor_name_from_pixmap(), and + * glamor_pixmap_from_fds() are supported. * * @screen: Current screen pointer. * @@ -161,11 +163,27 @@ extern _X_EXPORT struct gbm_device *glamor_egl_get_gbm_device(ScreenPtr screen); * * The EGL layer needs to have the following extensions working: * - * .EGL_KHR_gl_texture_2D_image - * .EGL_EXT_image_dma_buf_import + * .EGL_KHR_surfaceless_context * */ extern _X_EXPORT Bool glamor_supports_pixmap_import_export(ScreenPtr screen); +/* @glamor_fds_from_pixmap: Get a dma-buf fd from a pixmap. + * + * @screen: Current screen pointer. + * @pixmap: The pixmap from which we want the fd. + * @fds, @strides, @offsets: Pointers to fill info of each plane. + * @modifier: Pointer to fill the modifier of the buffer. + * + * the pixmap and the buffer associated by the fds will share the same + * content. The caller is responsible to close the returned file descriptors. + * Returns the number of planes, -1 on error. + * */ +extern _X_EXPORT int glamor_fds_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, + int *fds, + uint32_t *strides, uint32_t *offsets, + uint64_t *modifier); + /* @glamor_fd_from_pixmap: Get a dma-buf fd from a pixmap. * * @screen: Current screen pointer. @@ -231,6 +249,31 @@ extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap, extern _X_EXPORT struct gbm_bo *glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap); +/* @glamor_pixmap_from_fds: Creates a pixmap to wrap a dma-buf fds. + * + * @screen: Current screen pointer. + * @num_fds: Number of fds to import + * @fds: The dma-buf fds to import. + * @width: The width of the buffers. + * @height: The height of the buffers. + * @stride: The stride of the buffers. + * @depth: The depth of the buffers. + * @bpp: The bpp of the buffers. + * @modifier: The modifier of the buffers. + * + * Returns a valid pixmap if the import succeeded, else NULL. + * */ +extern _X_EXPORT PixmapPtr glamor_pixmap_from_fds(ScreenPtr screen, + CARD8 num_fds, + const int *fds, + CARD16 width, + CARD16 height, + const CARD32 *strides, + const CARD32 *offsets, + CARD8 depth, + CARD8 bpp, + uint64_t modifier); + /* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd. * * @screen: Current screen pointer. @@ -239,7 +282,7 @@ extern _X_EXPORT struct gbm_bo *glamor_gbm_bo_from_pixmap(ScreenPtr screen, * @height: The height of the buffer. * @stride: The stride of the buffer. * @depth: The depth of the buffer. - * @bpp: The number of bpp of the buffer. + * @bpp: The bpp of the buffer. * * Returns a valid pixmap if the import succeeded, else NULL. * */ @@ -270,6 +313,24 @@ extern _X_EXPORT Bool glamor_back_pixmap_from_fd(PixmapPtr pixmap, CARD16 stride, CARD8 depth, CARD8 bpp); + +extern _X_EXPORT Bool glamor_get_formats(ScreenPtr screen, + CARD32 *num_formats, + CARD32 **formats); + +extern _X_EXPORT Bool glamor_get_modifiers(ScreenPtr screen, + uint32_t format, + uint32_t *num_modifiers, + uint64_t **modifiers); + +extern _X_EXPORT Bool glamor_get_drawable_modifiers(DrawablePtr draw, + uint32_t format, + uint32_t *num_modifiers, + uint64_t **modifiers); + +extern _X_EXPORT void glamor_set_drawable_modifiers_func(ScreenPtr screen, + GetDrawableModifiersFuncPtr func); + #ifdef GLAMOR_FOR_XORG #define GLAMOR_EGL_MODULE_NAME "glamoregl" @@ -299,17 +360,11 @@ extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); extern _X_EXPORT Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride); -/* @glamor_egl_create_textured_screen_ext: - * - * extent one parameter to track the pointer of the DDX layer's back pixmap. - * We need this pointer during the closing screen stage. As before back to - * the DDX's close screen, we have to free all the glamor related resources. +/* Obsolete entrypoint, temporarily left here for API compatibility + * for xf86-video-ati. */ -extern _X_EXPORT Bool glamor_egl_create_textured_screen_ext(ScreenPtr screen, - int handle, - int stride, - PixmapPtr - *back_pixmap); +#define glamor_egl_create_textured_screen_ext(a, b, c, d) \ + glamor_egl_create_textured_screen(a, b, c) /* * @glamor_egl_create_textured_pixmap: Try to create a textured pixmap from @@ -337,7 +392,8 @@ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, */ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, - struct gbm_bo *bo); + struct gbm_bo *bo, + Bool used_modifiers); #endif diff --git a/xserver/glamor/glamor_copy.c b/xserver/glamor/glamor_copy.c index ed96b2b1e..e050c0220 100644 --- a/xserver/glamor/glamor_copy.c +++ b/xserver/glamor/glamor_copy.c @@ -78,6 +78,15 @@ use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg) /* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap private knows this? */ switch (args->src_pixmap->drawable.depth) { + case 30: + glUniform4ui(prog->bitplane_uniform, + (args->bitplane >> 20) & 0x3ff, + (args->bitplane >> 10) & 0x3ff, + (args->bitplane ) & 0x3ff, + 0); + + glUniform4f(prog->bitmul_uniform, 0x3ff, 0x3ff, 0x3ff, 0); + break; case 24: glUniform4ui(prog->bitplane_uniform, (args->bitplane >> 16) & 0xff, @@ -180,7 +189,7 @@ glamor_copy_bail(DrawablePtr src, } /** - * Implements CopyPlane and CopyArea from the GPU to the GPU by using + * Implements CopyPlane and CopyArea from the CPU to the GPU by using * the source as a texture and painting that into the destination. * * This requires that source and dest are different textures, or that @@ -203,10 +212,6 @@ glamor_copy_cpu_fbo(DrawablePtr src, ScreenPtr screen = dst->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - FbBits *src_bits; - FbStride src_stride; - int src_bpp; - int src_xoff, src_yoff; int dst_xoff, dst_yoff; if (gc && gc->alu != GXcopy) @@ -221,33 +226,43 @@ glamor_copy_cpu_fbo(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff); if (bitplane) { - PixmapPtr src_pix = fbCreatePixmap(screen, dst_pixmap->drawable.width, + FbBits *tmp_bits; + FbStride tmp_stride; + int tmp_bpp; + int tmp_xoff, tmp_yoff; + + PixmapPtr tmp_pix = fbCreatePixmap(screen, dst_pixmap->drawable.width, dst_pixmap->drawable.height, dst->depth, 0); - if (!src_pix) { + if (!tmp_pix) { glamor_finish_access(src); goto bail; } - src_pix->drawable.x = dst_xoff; - src_pix->drawable.y = dst_yoff; + tmp_pix->drawable.x = dst_xoff; + tmp_pix->drawable.y = dst_yoff; - fbGetDrawable(&src_pix->drawable, src_bits, src_stride, src_bpp, src_xoff, - src_yoff); + fbGetDrawable(&tmp_pix->drawable, tmp_bits, tmp_stride, tmp_bpp, tmp_xoff, + tmp_yoff); if (src->bitsPerPixel > 1) - fbCopyNto1(src, &src_pix->drawable, gc, box, nbox, dx, dy, + fbCopyNto1(src, &tmp_pix->drawable, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); else - fbCopy1toN(src, &src_pix->drawable, gc, box, nbox, dx, dy, + fbCopy1toN(src, &tmp_pix->drawable, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); - glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff, src_yoff, - dst_xoff, dst_yoff, (uint8_t *) src_bits, - src_stride * sizeof(FbBits)); - fbDestroyPixmap(src_pix); + glamor_upload_boxes(dst_pixmap, box, nbox, tmp_xoff, tmp_yoff, + dst_xoff, dst_yoff, (uint8_t *) tmp_bits, + tmp_stride * sizeof(FbBits)); + fbDestroyPixmap(tmp_pix); } else { + FbBits *src_bits; + FbStride src_stride; + int src_bpp; + int src_xoff, src_yoff; + fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff); glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff + dy, dst_xoff, dst_yoff, @@ -311,6 +326,13 @@ bail: return FALSE; } +/* Include the enums here for the moment, to keep from needing to bump epoxy. */ +#ifndef GL_TILE_RASTER_ORDER_FIXED_MESA +#define GL_TILE_RASTER_ORDER_FIXED_MESA 0x8BB8 +#define GL_TILE_RASTER_ORDER_INCREASING_X_MESA 0x8BB9 +#define GL_TILE_RASTER_ORDER_INCREASING_Y_MESA 0x8BBA +#endif + /* * Copy from GPU to GPU by using the source * as a texture and painting that into the destination @@ -345,6 +367,7 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, const glamor_facet *copy_facet; int n; Bool ret = FALSE; + BoxRec bounds = glamor_no_rendering_bounds(); glamor_make_current(glamor_priv); @@ -381,15 +404,34 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset); + if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) { + glEnable(GL_TILE_RASTER_ORDER_FIXED_MESA); + if (dx >= 0) + glEnable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA); + else + glDisable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA); + if (dy >= 0) + glEnable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA); + else + glDisable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA); + } + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 2 * sizeof (GLshort), vbo_offset); + if (nbox < 100) { + bounds = glamor_start_rendering_bounds(); + for (int i = 0; i < nbox; i++) + glamor_bounds_union_box(&bounds, &box[i]); + } + for (n = 0; n < nbox; n++) { v[0] = box->x1; v[1] = box->y1; v[2] = box->x1; v[3] = box->y2; v[4] = box->x2; v[5] = box->y2; v[6] = box->x2; v[7] = box->y1; + v += 8; box++; } @@ -411,15 +453,24 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, goto bail_ctx; glamor_pixmap_loop(dst_priv, dst_box_index) { + BoxRec scissor = { + .x1 = max(-args.dx, bounds.x1), + .y1 = max(-args.dy, bounds.y1), + .x2 = min(-args.dx + src_box->x2 - src_box->x1, bounds.x2), + .y2 = min(-args.dy + src_box->y2 - src_box->y1, bounds.y2), + }; + if (scissor.x1 >= scissor.x2 || scissor.y1 >= scissor.y2) + continue; + if (!glamor_set_destination_drawable(dst, dst_box_index, FALSE, FALSE, prog->matrix_uniform, &dst_off_x, &dst_off_y)) goto bail_ctx; - glScissor(dst_off_x - args.dx, - dst_off_y - args.dy, - src_box->x2 - src_box->x1, - src_box->y2 - src_box->y1); + glScissor(scissor.x1 + dst_off_x, + scissor.y1 + dst_off_y, + scissor.x2 - scissor.x1, + scissor.y2 - scissor.y1); glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox); } @@ -428,6 +479,9 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, ret = TRUE; bail_ctx: + if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) { + glDisable(GL_TILE_RASTER_ORDER_FIXED_MESA); + } glDisable(GL_SCISSOR_TEST); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); @@ -588,34 +642,36 @@ glamor_copy_needs_temp(DrawablePtr src, if (!glamor_priv->has_nv_texture_barrier) return TRUE; - glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y); - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y); + if (!glamor_priv->has_mesa_tile_raster_order) { + glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y); - bounds = box[0]; - for (n = 1; n < nbox; n++) { - bounds.x1 = min(bounds.x1, box[n].x1); - bounds.y1 = min(bounds.y1, box[n].y1); + bounds = box[0]; + for (n = 1; n < nbox; n++) { + bounds.x1 = min(bounds.x1, box[n].x1); + bounds.y1 = min(bounds.y1, box[n].y1); - bounds.x2 = max(bounds.x2, box[n].x2); - bounds.y2 = max(bounds.y2, box[n].y2); - } - - /* Check to see if the pixmap-relative boxes overlap in both X and Y, - * in which case we can't rely on NV_texture_barrier and must - * make a temporary copy - * - * dst.x1 < src.x2 && - * src.x1 < dst.x2 && - * - * dst.y1 < src.y2 && - * src.y1 < dst.y2 - */ - if (bounds.x1 + dst_off_x < bounds.x2 + dx + src_off_x && - bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x && + bounds.x2 = max(bounds.x2, box[n].x2); + bounds.y2 = max(bounds.y2, box[n].y2); + } - bounds.y1 + dst_off_y < bounds.y2 + dy + src_off_y && - bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) { - return TRUE; + /* Check to see if the pixmap-relative boxes overlap in both X and Y, + * in which case we can't rely on NV_texture_barrier and must + * make a temporary copy + * + * dst.x1 < src.x2 && + * src.x1 < dst.x2 && + * + * dst.y1 < src.y2 && + * src.y1 < dst.y2 + */ + if (bounds.x1 + dst_off_x < bounds.x2 + dx + src_off_x && + bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x && + + bounds.y1 + dst_off_y < bounds.y2 + dy + src_off_y && + bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) { + return TRUE; + } } glTextureBarrierNV(); diff --git a/xserver/glamor/glamor_core.c b/xserver/glamor/glamor_core.c index 7b2b39633..cb315e2d1 100644 --- a/xserver/glamor/glamor_core.c +++ b/xserver/glamor/glamor_core.c @@ -40,12 +40,9 @@ glamor_get_drawable_location(const DrawablePtr drawable) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(drawable->pScreen); + if (pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) return 'm'; - if (pixmap_priv->fbo->fb == glamor_priv->screen_fbo) - return 's'; else return 'f'; } @@ -200,43 +197,6 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) * Preempt fbValidateGC by doing its work and masking the change out, so * that we can do the Prepare/finish_access. */ -#ifdef FB_24_32BIT - if ((changes & GCTile) && fbGetRotatedPixmap(gc)) { - gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); - fbGetRotatedPixmap(gc) = 0; - } - - if (gc->fillStyle == FillTiled) { - PixmapPtr old_tile, new_tile; - - old_tile = gc->tile.pixmap; - if (old_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { - new_tile = fbGetRotatedPixmap(gc); - if (!new_tile || - new_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { - if (new_tile) - gc->pScreen->DestroyPixmap(new_tile); - /* fb24_32ReformatTile will do direct access of a newly- - * allocated pixmap. - */ - glamor_fallback - ("GC %p tile FB_24_32 transformat %p.\n", gc, old_tile); - - if (glamor_prepare_access - (&old_tile->drawable, GLAMOR_ACCESS_RO)) { - new_tile = - fb24_32ReformatTile(old_tile, drawable->bitsPerPixel); - glamor_finish_access(&old_tile->drawable); - } - } - if (new_tile) { - fbGetRotatedPixmap(gc) = old_tile; - gc->tile.pixmap = new_tile; - changes |= GCTile; - } - } - } -#endif if (changes & GCTile) { if (!gc->tileIsPixel) { glamor_pixmap_private *pixmap_priv = diff --git a/xserver/glamor/glamor_debug.h b/xserver/glamor/glamor_debug.h index 638bee20c..f64c44832 100644 --- a/xserver/glamor/glamor_debug.h +++ b/xserver/glamor/glamor_debug.h @@ -29,8 +29,6 @@ #ifndef __GLAMOR_DEBUG_H__ #define __GLAMOR_DEBUG_H__ -#define GLAMOR_DELAYED_STRING_MAX 64 - #define GLAMOR_DEBUG_NONE 0 #define GLAMOR_DEBUG_UNIMPL 0 #define GLAMOR_DEBUG_FALLBACK 1 @@ -72,33 +70,6 @@ AbortServer(void) "Glamor fallback", \ ##__VA_ARGS__);} while(0) -#define glamor_delayed_fallback(_screen_, _format_,...) \ - do { \ - if (glamor_debug_level >= GLAMOR_DEBUG_FALLBACK) { \ - glamor_screen_private *_glamor_priv_; \ - _glamor_priv_ = glamor_get_screen_private(_screen_); \ - _glamor_priv_->delayed_fallback_pending = 1; \ - snprintf(_glamor_priv_->delayed_fallback_string, \ - GLAMOR_DELAYED_STRING_MAX, \ - "glamor delayed fallback: \t%s " _format_ , \ - __FUNCTION__, ##__VA_ARGS__); } } while(0) - -#define glamor_clear_delayed_fallbacks(_screen_) \ - do { \ - if (glamor_debug_level >= GLAMOR_DEBUG_FALLBACK) { \ - glamor_screen_private *_glamor_priv_; \ - _glamor_priv_ = glamor_get_screen_private(_screen_); \ - _glamor_priv_->delayed_fallback_pending = 0; } } while(0) - -#define glamor_report_delayed_fallbacks(_screen_) \ - do { \ - if (glamor_debug_level >= GLAMOR_DEBUG_FALLBACK) { \ - glamor_screen_private *_glamor_priv_; \ - _glamor_priv_ = glamor_get_screen_private(_screen_); \ - LogMessageVerb(X_INFO, 0, "%s", \ - _glamor_priv_->delayed_fallback_string); \ - _glamor_priv_->delayed_fallback_pending = 0; } } while(0) - #define DEBUGF(str, ...) do {} while(0) //#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) #define DEBUGRegionPrint(x) do {} while (0) diff --git a/xserver/glamor/glamor_egl.c b/xserver/glamor/glamor_egl.c index c9955e89b..a78e7104b 100644 --- a/xserver/glamor/glamor_egl.c +++ b/xserver/glamor/glamor_egl.c @@ -35,13 +35,12 @@ #include <sys/ioctl.h> #include <errno.h> #include <xf86.h> +#include <xf86Priv.h> #include <xf86drm.h> #define EGL_DISPLAY_NO_X_MESA -#ifdef GLAMOR_HAS_GBM #include <gbm.h> #include <drm_fourcc.h> -#endif #include "glamor_egl.h" @@ -49,31 +48,16 @@ #include "glamor_priv.h" #include "dri3.h" -static const char glamor_name[] = "glamor"; - -static void -glamor_identify(int flags) -{ - xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver based.\n", - glamor_name); -} - struct glamor_egl_screen_private { EGLDisplay display; EGLContext context; - EGLint major, minor; char *device_path; CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; int fd; - int cpp; -#ifdef GLAMOR_HAS_GBM struct gbm_device *gbm; -#endif - int has_gem; - int gl_context_depth; - int dri3_capable; + int dmabuf_capable; CloseScreenProcPtr saved_close_screen; DestroyPixmapProcPtr saved_destroy_pixmap; @@ -109,46 +93,24 @@ glamor_egl_make_current(struct glamor_context *glamor_ctx) } } -static EGLImageKHR -_glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, - int width, int height, int stride, int name, int depth) -{ - EGLImageKHR image; - - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, - EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, - EGL_DRM_BUFFER_USE_SHARE_MESA | EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - attribs[1] = width; - attribs[3] = height; - attribs[5] = stride; - if (depth != 32 && depth != 24) - return EGL_NO_IMAGE_KHR; - image = eglCreateImageKHR(glamor_egl->display, - glamor_egl->context, - EGL_DRM_BUFFER_MESA, - (void *) (uintptr_t) name, - attribs); - if (image == EGL_NO_IMAGE_KHR) - return EGL_NO_IMAGE_KHR; - - return image; -} - static int glamor_get_flink_name(int fd, int handle, int *name) { struct drm_gem_flink flink; flink.handle = handle; - if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) - return FALSE; + if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { + + /* + * Assume non-GEM kernels have names identical to the handle + */ + if (errno == ENODEV) { + *name = handle; + return TRUE; + } else { + return FALSE; + } + } *name = flink.name; return TRUE; } @@ -176,13 +138,9 @@ glamor_create_texture_from_image(ScreenPtr screen, struct gbm_device * glamor_egl_get_gbm_device(ScreenPtr screen) { -#ifdef GLAMOR_HAS_GBM struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); return glamor_egl->gbm; -#else - return NULL; -#endif } Bool @@ -198,33 +156,12 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) "Failed to create textured screen."); return FALSE; } - glamor_set_screen_pixmap(screen_pixmap, NULL); return TRUE; } -Bool -glamor_egl_create_textured_screen_ext(ScreenPtr screen, - int handle, - int stride, PixmapPtr *back_pixmap) -{ - return glamor_egl_create_textured_screen(screen, handle, stride); -} - -static Bool -glamor_egl_check_has_gem(int fd) -{ - struct drm_gem_flink flink; - - flink.handle = 0; - - ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - if (errno == ENOENT || errno == EINVAL) - return TRUE; - return FALSE; -} - static void -glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image) +glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image, + Bool used_modifiers) { struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -239,6 +176,7 @@ glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image) eglDestroyImageKHR(glamor_egl->display, old); } pixmap_priv->image = image; + pixmap_priv->used_modifiers = used_modifiers; } Bool @@ -246,52 +184,40 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - struct glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - struct glamor_egl_screen_private *glamor_egl; - EGLImageKHR image; - GLuint texture; - int name; - Bool ret = FALSE; - - glamor_egl = glamor_egl_get_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + int ret, fd; - glamor_make_current(glamor_priv); - if (glamor_egl->has_gem) { - if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Couldn't flink pixmap handle\n"); - glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); - assert(0); - return FALSE; - } + /* GBM doesn't have an import path from handles, so we make a + * dma-buf fd from it and then go through that. + */ + ret = drmPrimeHandleToFD(glamor_egl->fd, handle, O_CLOEXEC, &fd); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make prime FD for handle: %d\n", errno); + return FALSE; } - else - name = handle; - - image = _glamor_egl_create_image(glamor_egl, - pixmap->drawable.width, - pixmap->drawable.height, - ((stride * 8 + - 7) / pixmap->drawable.bitsPerPixel), - name, pixmap->drawable.depth); - if (image == EGL_NO_IMAGE_KHR) { - glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); - goto done; + + if (!glamor_back_pixmap_from_fd(pixmap, fd, + pixmap->drawable.width, + pixmap->drawable.height, + stride, + pixmap->drawable.depth, + pixmap->drawable.bitsPerPixel)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make import prime FD as pixmap: %d\n", errno); + close(fd); + return FALSE; } - glamor_create_texture_from_image(screen, image, &texture); - glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); - glamor_set_pixmap_texture(pixmap, texture); - glamor_egl_set_pixmap_image(pixmap, image); - ret = TRUE; - done: - return ret; + close(fd); + return TRUE; } Bool glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, - struct gbm_bo *bo) + struct gbm_bo *bo, + Bool used_modifiers) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); @@ -316,14 +242,13 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, glamor_create_texture_from_image(screen, image, &texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_texture(pixmap, texture); - glamor_egl_set_pixmap_image(pixmap, image); + glamor_egl_set_pixmap_image(pixmap, image, used_modifiers); ret = TRUE; done: return ret; } -#ifdef GLAMOR_HAS_GBM static void glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name) { @@ -333,12 +258,10 @@ glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name) if (!glamor_get_flink_name(gbm_fd, handle.u32, name)) *name = -1; } -#endif static Bool -glamor_make_pixmap_exportable(PixmapPtr pixmap) +glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) { -#ifdef GLAMOR_HAS_GBM ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = @@ -347,11 +270,14 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap) glamor_get_pixmap_private(pixmap); unsigned width = pixmap->drawable.width; unsigned height = pixmap->drawable.height; - struct gbm_bo *bo; + uint32_t format; + struct gbm_bo *bo = NULL; + Bool used_modifiers = FALSE; PixmapPtr exported; GCPtr scratch_gc; - if (pixmap_priv->image) + if (pixmap_priv->image && + (modifiers_ok || !pixmap_priv->used_modifiers)) return TRUE; if (pixmap->drawable.bitsPerPixel != 32) { @@ -361,13 +287,36 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap) return FALSE; } - bo = gbm_bo_create(glamor_egl->gbm, width, height, - GBM_FORMAT_ARGB8888, + if (pixmap->drawable.depth == 30) + format = GBM_FORMAT_ARGB2101010; + else + format = GBM_FORMAT_ARGB8888; + +#ifdef GBM_BO_WITH_MODIFIERS + if (modifiers_ok && glamor_egl->dmabuf_capable) { + uint32_t num_modifiers; + uint64_t *modifiers = NULL; + + glamor_get_modifiers(screen, format, &num_modifiers, &modifiers); + + bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height, + format, modifiers, num_modifiers); + if (bo) + used_modifiers = TRUE; + free(modifiers); + } +#endif + + if (!bo) + { + bo = gbm_bo_create(glamor_egl->gbm, width, height, format, #ifdef GLAMOR_HAS_GBM_LINEAR - (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ? - GBM_BO_USE_LINEAR : 0) | + (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ? + GBM_BO_USE_LINEAR : 0) | #endif - GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); + GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); + } + if (!bo) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to make %dx%dx%dbpp GBM bo\n", @@ -378,7 +327,8 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap) exported = screen->CreatePixmap(screen, 0, 0, pixmap->drawable.depth, 0); screen->ModifyPixmapHeader(exported, width, height, 0, 0, gbm_bo_get_stride(bo), NULL); - if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo)) { + if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo, + used_modifiers)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to make %dx%dx%dbpp pixmap from GBM bo\n", width, height, pixmap->drawable.bitsPerPixel); @@ -403,9 +353,6 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap) screen->DestroyPixmap(exported); return TRUE; -#else - return FALSE; -#endif } struct gbm_bo * @@ -416,7 +363,7 @@ glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - if (!glamor_make_pixmap_exportable(pixmap)) + if (!pixmap_priv->image) return NULL; return gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, @@ -424,40 +371,100 @@ glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) } int -glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, - PixmapPtr pixmap, - unsigned int tex, - Bool want_name, CARD16 *stride, CARD32 *size) +glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *strides, uint32_t *offsets, + uint64_t *modifier) +{ +#ifdef GLAMOR_HAS_GBM + struct gbm_bo *bo; + int num_fds; +#ifdef GBM_BO_WITH_MODIFIERS + int i; +#endif + + if (!glamor_make_pixmap_exportable(pixmap, TRUE)) + return 0; + + bo = glamor_gbm_bo_from_pixmap(screen, pixmap); + if (!bo) + return 0; + +#ifdef GBM_BO_WITH_MODIFIERS + num_fds = gbm_bo_get_plane_count(bo); + for (i = 0; i < num_fds; i++) { + fds[i] = gbm_bo_get_fd(bo); + strides[i] = gbm_bo_get_stride_for_plane(bo, i); + offsets[i] = gbm_bo_get_offset(bo, i); + } + *modifier = gbm_bo_get_modifier(bo); +#else + num_fds = 1; + fds[0] = gbm_bo_get_fd(bo); + strides[0] = gbm_bo_get_stride(bo); + offsets[0] = 0; + *modifier = DRM_FORMAT_MOD_INVALID; +#endif + + gbm_bo_destroy(bo); + return num_fds; +#else + return 0; +#endif +} + +_X_EXPORT int +glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, + CARD16 *stride, CARD32 *size) { #ifdef GLAMOR_HAS_GBM + struct gbm_bo *bo; + int fd; + + if (!glamor_make_pixmap_exportable(pixmap, FALSE)) + return -1; + + bo = glamor_gbm_bo_from_pixmap(screen, pixmap); + if (!bo) + return -1; + + fd = gbm_bo_get_fd(bo); + *stride = gbm_bo_get_stride(bo); + *size = *stride * gbm_bo_get_height(bo); + gbm_bo_destroy(bo); + + return fd; +#else + return -1; +#endif +} + +int +glamor_egl_fd_name_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, CARD32 *size) +{ struct glamor_egl_screen_private *glamor_egl; struct gbm_bo *bo; int fd = -1; glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + if (!glamor_make_pixmap_exportable(pixmap, FALSE)) + goto failure; + bo = glamor_gbm_bo_from_pixmap(screen, pixmap); if (!bo) goto failure; pixmap->devKind = gbm_bo_get_stride(bo); - if (want_name) { - if (glamor_egl->has_gem) - glamor_get_name_from_bo(glamor_egl->fd, bo, &fd); - } - else { - fd = gbm_bo_get_fd(bo); - } + glamor_get_name_from_bo(glamor_egl->fd, bo, &fd); *stride = pixmap->devKind; *size = pixmap->devKind * gbm_bo_get_height(bo); gbm_bo_destroy(bo); failure: return fd; -#else - return -1; -#endif } _X_EXPORT Bool @@ -467,7 +474,6 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) { -#ifdef GLAMOR_HAS_GBM ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; @@ -477,29 +483,97 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap, glamor_egl = glamor_egl_get_screen_private(scrn); - if (!glamor_egl->dri3_capable) - return FALSE; - - if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 || height == 0) + if (bpp != 32 || !(depth == 24 || depth == 32 || depth == 30) || width == 0 || height == 0) return FALSE; import_data.fd = fd; import_data.width = width; import_data.height = height; import_data.stride = stride; - import_data.format = GBM_FORMAT_ARGB8888; + if (depth == 30) + import_data.format = GBM_FORMAT_ARGB2101010; + else + import_data.format = GBM_FORMAT_ARGB8888; bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD, &import_data, 0); if (!bo) return FALSE; screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL); - ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); + ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, FALSE); gbm_bo_destroy(bo); return ret; -#else - return FALSE; +} + +static uint32_t +gbm_format_for_depth(CARD8 depth) +{ + switch (depth) { + case 16: + return GBM_FORMAT_RGB565; + case 24: + return GBM_FORMAT_XRGB8888; + case 30: + return GBM_FORMAT_ARGB2101010; + default: + ErrorF("unexpected depth: %d\n", depth); + case 32: + return GBM_FORMAT_ARGB8888; + } +} + +_X_EXPORT PixmapPtr +glamor_pixmap_from_fds(ScreenPtr screen, + CARD8 num_fds, const int *fds, + CARD16 width, CARD16 height, + const CARD32 *strides, const CARD32 *offsets, + CARD8 depth, CARD8 bpp, + uint64_t modifier) +{ + PixmapPtr pixmap; + struct glamor_egl_screen_private *glamor_egl; + Bool ret = FALSE; + int i; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + + pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); + +#ifdef GBM_BO_WITH_MODIFIERS + if (glamor_egl->dmabuf_capable && modifier != DRM_FORMAT_MOD_INVALID) { + struct gbm_import_fd_modifier_data import_data = { 0 }; + struct gbm_bo *bo; + + import_data.width = width; + import_data.height = height; + import_data.num_fds = num_fds; + import_data.modifier = modifier; + for (i = 0; i < num_fds; i++) { + import_data.fds[i] = fds[i]; + import_data.strides[i] = strides[i]; + import_data.offsets[i] = offsets[i]; + } + import_data.format = gbm_format_for_depth(depth); + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0); + if (bo) { + screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL); + ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, TRUE); + gbm_bo_destroy(bo); + } + } else #endif + { + if (num_fds == 1) { + ret = glamor_back_pixmap_from_fd(pixmap, fds[0], width, height, + strides[0], depth, bpp); + } + } + + if (ret == FALSE) { + screen->DestroyPixmap(pixmap); + return NULL; + } + return pixmap; } _X_EXPORT PixmapPtr @@ -509,20 +583,99 @@ glamor_pixmap_from_fd(ScreenPtr screen, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) { -#ifdef GLAMOR_HAS_GBM PixmapPtr pixmap; Bool ret; pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); + ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height, stride, depth, bpp); + if (ret == FALSE) { screen->DestroyPixmap(pixmap); return NULL; } return pixmap; +} + +_X_EXPORT Bool +glamor_get_formats(ScreenPtr screen, + CARD32 *num_formats, CARD32 **formats) +{ +#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF + struct glamor_egl_screen_private *glamor_egl; + EGLint num; + + /* Explicitly zero the count as the caller may ignore the return value */ + *num_formats = 0; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + + if (!glamor_egl->dmabuf_capable) + return TRUE; + + if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, 0, NULL, &num)) + return FALSE; + + if (num == 0) + return TRUE; + + *formats = calloc(num, sizeof(CARD32)); + if (*formats == NULL) + return FALSE; + + if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, num, + (EGLint *) *formats, &num)) { + free(*formats); + return FALSE; + } + + *num_formats = num; + return TRUE; +#else + *num_formats = 0; + return TRUE; +#endif +} + +_X_EXPORT Bool +glamor_get_modifiers(ScreenPtr screen, uint32_t format, + uint32_t *num_modifiers, uint64_t **modifiers) +{ +#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF + struct glamor_egl_screen_private *glamor_egl; + EGLint num; + + /* Explicitly zero the count as the caller may ignore the return value */ + *num_modifiers = 0; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + + if (!glamor_egl->dmabuf_capable) + return FALSE; + + if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, 0, NULL, + NULL, &num)) + return FALSE; + + if (num == 0) + return TRUE; + + *modifiers = calloc(num, sizeof(uint64_t)); + if (*modifiers == NULL) + return FALSE; + + if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, num, + (EGLuint64KHR *) *modifiers, NULL, &num)) { + free(*modifiers); + return FALSE; + } + + *num_modifiers = num; + return TRUE; #else - return NULL; + *num_modifiers = 0; + return TRUE; #endif } @@ -554,7 +707,8 @@ glamor_egl_destroy_pixmap(PixmapPtr pixmap) _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) { - EGLImageKHR temp; + EGLImageKHR temp_img; + Bool temp_mod; struct glamor_pixmap_private *front_priv = glamor_get_pixmap_private(front); struct glamor_pixmap_private *back_priv = @@ -562,9 +716,12 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) glamor_pixmap_exchange_fbos(front, back); - temp = back_priv->image; + temp_img = back_priv->image; + temp_mod = back_priv->used_modifiers; back_priv->image = front_priv->image; - front_priv->image = temp; + back_priv->used_modifiers = front_priv->used_modifiers; + front_priv->image = temp_img; + front_priv->used_modifiers = temp_mod; glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM); @@ -646,11 +803,15 @@ glamor_dri3_open_client(ClientPtr client, return Success; } -static dri3_screen_info_rec glamor_dri3_info = { - .version = 1, +static const dri3_screen_info_rec glamor_dri3_info = { + .version = 2, .open_client = glamor_dri3_open_client, - .pixmap_from_fd = glamor_pixmap_from_fd, - .fd_from_pixmap = glamor_fd_from_pixmap, + .pixmap_from_fds = glamor_pixmap_from_fds, + .fd_from_pixmap = glamor_egl_fd_from_pixmap, + .fds_from_pixmap = glamor_egl_fds_from_pixmap, + .get_formats = glamor_get_formats, + .get_modifiers = glamor_get_modifiers, + .get_drawable_modifiers = glamor_get_drawable_modifiers, }; #endif /* DRI3 */ @@ -660,6 +821,9 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); +#ifdef DRI3 + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); +#endif glamor_egl->saved_close_screen = screen->CloseScreen; screen->CloseScreen = glamor_egl_close_screen; @@ -673,28 +837,25 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) glamor_ctx->make_current = glamor_egl_make_current; #ifdef DRI3 - if (glamor_egl->dri3_capable) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - /* Tell the core that we have the interfaces for import/export - * of pixmaps. - */ - glamor_enable_dri3(screen); + /* Tell the core that we have the interfaces for import/export + * of pixmaps. + */ + glamor_enable_dri3(screen); - /* If the driver wants to do its own auth dance (e.g. Xwayland - * on pre-3.15 kernels that don't have render nodes and thus - * has the wayland compositor as a master), then it needs us - * to stay out of the way and let it init DRI3 on its own. + /* If the driver wants to do its own auth dance (e.g. Xwayland + * on pre-3.15 kernels that don't have render nodes and thus + * has the wayland compositor as a master), then it needs us + * to stay out of the way and let it init DRI3 on its own. + */ + if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) { + /* To do DRI3 device FD generation, we need to open a new fd + * to the same device we were handed in originally. */ - if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) { - /* To do DRI3 device FD generation, we need to open a new fd - * to the same device we were handed in originally. - */ - glamor_egl->device_path = drmGetDeviceNameFromFd(glamor_egl->fd); + glamor_egl->device_path = drmGetDeviceNameFromFd2(glamor_egl->fd); - if (!dri3_screen_init(screen, &glamor_dri3_info)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to initialize DRI3.\n"); - } + if (!dri3_screen_init(screen, &glamor_dri3_info)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to initialize DRI3.\n"); } } #endif @@ -712,10 +873,8 @@ static void glamor_egl_cleanup(struct glamor_egl_screen_private *glamor_egl) lastGLContext = NULL; eglTerminate(glamor_egl->display); } -#ifdef GLAMOR_HAS_GBM if (glamor_egl->gbm) gbm_device_destroy(glamor_egl->gbm); -#endif free(glamor_egl->device_path); free(glamor_egl); } @@ -737,25 +896,8 @@ Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) { struct glamor_egl_screen_private *glamor_egl; - const char *version; + const GLubyte *renderer; - EGLint config_attribs[] = { -#ifdef GLAMOR_GLES2 - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - static const EGLint config_attribs_core[] = { - EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, - EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, - EGL_CONTEXT_MAJOR_VERSION_KHR, - GLAMOR_GL_CORE_VER_MAJOR, - EGL_CONTEXT_MINOR_VERSION_KHR, - GLAMOR_GL_CORE_VER_MINOR, - EGL_NONE - }; - - glamor_identify(0); glamor_egl = calloc(sizeof(*glamor_egl), 1); if (glamor_egl == NULL) return FALSE; @@ -764,7 +906,6 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl; glamor_egl->fd = fd; -#ifdef GLAMOR_HAS_GBM glamor_egl->gbm = gbm_create_device(glamor_egl->fd); if (glamor_egl->gbm == NULL) { ErrorF("couldn't get display device\n"); @@ -777,28 +918,13 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetDisplay() failed\n"); goto error; } -#else - glamor_egl->display = eglGetDisplay((EGLNativeDisplayType) (intptr_t) fd); -#endif - - glamor_egl->has_gem = glamor_egl_check_has_gem(fd); - if (!eglInitialize - (glamor_egl->display, &glamor_egl->major, &glamor_egl->minor)) { + if (!eglInitialize(glamor_egl->display, NULL, NULL)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n"); glamor_egl->display = EGL_NO_DISPLAY; goto error; } -#ifndef GLAMOR_GLES2 - eglBindAPI(EGL_OPENGL_API); -#else - eglBindAPI(EGL_OPENGL_ES_API); -#endif - - version = eglQueryString(glamor_egl->display, EGL_VERSION); - xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); - #define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT)) { \ ErrorF("EGL_" #EXT " required.\n"); \ @@ -812,30 +938,51 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) goto error; \ } - GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); - GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); -#ifdef GLAMOR_GLES2 - GLAMOR_CHECK_EGL_EXTENSIONS(KHR_surfaceless_context, KHR_surfaceless_gles2); -#else - GLAMOR_CHECK_EGL_EXTENSIONS(KHR_surfaceless_context, - KHR_surfaceless_opengl); -#endif + GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_context); + + if (eglBindAPI(EGL_OPENGL_API)) { + static const EGLint config_attribs_core[] = { + EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, + EGL_CONTEXT_MAJOR_VERSION_KHR, + GLAMOR_GL_CORE_VER_MAJOR, + EGL_CONTEXT_MINOR_VERSION_KHR, + GLAMOR_GL_CORE_VER_MINOR, + EGL_NONE + }; + static const EGLint config_attribs[] = { + EGL_NONE + }; -#ifndef GLAMOR_GLES2 - glamor_egl->context = eglCreateContext(glamor_egl->display, - NULL, EGL_NO_CONTEXT, - config_attribs_core); -#else - glamor_egl->context = NULL; -#endif - if (!glamor_egl->context) { glamor_egl->context = eglCreateContext(glamor_egl->display, NULL, EGL_NO_CONTEXT, - config_attribs); - if (glamor_egl->context == EGL_NO_CONTEXT) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n"); + config_attribs_core); + + if (glamor_egl->context == EGL_NO_CONTEXT) + glamor_egl->context = eglCreateContext(glamor_egl->display, + NULL, EGL_NO_CONTEXT, + config_attribs); + } + + if (glamor_egl->context == EGL_NO_CONTEXT) { + static const EGLint config_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + if (!eglBindAPI(EGL_OPENGL_ES_API)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "glamor: Failed to bind either GL or GLES APIs.\n"); goto error; } + + glamor_egl->context = eglCreateContext(glamor_egl->display, + NULL, EGL_NO_CONTEXT, + config_attribs); + } + if (glamor_egl->context == EGL_NO_CONTEXT) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "glamor: Failed to create GL or GLES2 contexts\n"); + goto error; } if (!eglMakeCurrent(glamor_egl->display, @@ -844,26 +991,49 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) "Failed to make EGL context current\n"); goto error; } + + renderer = glGetString(GL_RENDERER); + if (!renderer) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "glGetString() returned NULL, your GL is broken\n"); + goto error; + } + if (strstr((const char *)renderer, "llvmpipe")) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Refusing to try glamor on llvmpipe\n"); + goto error; + } + /* * Force the next glamor_make_current call to set the right context * (in case of multiple GPUs using glamor) */ lastGLContext = NULL; -#ifdef GLAMOR_HAS_GBM + + if (!epoxy_has_gl_extension("GL_OES_EGL_image")) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "glamor acceleration requires GL_OES_EGL_image\n"); + goto error; + } + + xf86DrvMsg(scrn->scrnIndex, X_INFO, "glamor X acceleration enabled on %s\n", + renderer); + +#ifdef GBM_BO_WITH_MODIFIERS if (epoxy_has_egl_extension(glamor_egl->display, - "EGL_KHR_gl_texture_2D_image") && - epoxy_has_gl_extension("GL_OES_EGL_image")) - glamor_egl->dri3_capable = TRUE; + "EGL_EXT_image_dma_buf_import") && + epoxy_has_egl_extension(glamor_egl->display, + "EGL_EXT_image_dma_buf_import_modifiers")) { + if (xf86Info.debug != NULL) + glamor_egl->dmabuf_capable = !!strstr(xf86Info.debug, + "dmabuf_capable"); + else + glamor_egl->dmabuf_capable = FALSE; + } #endif glamor_egl->saved_free_screen = scrn->FreeScreen; scrn->FreeScreen = glamor_egl_free_screen; -#ifdef GLAMOR_GLES2 - xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using GLES2.\n"); - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Glamor is using GLES2 but GLX needs GL. " - "Indirect GLX may not work correctly.\n"); -#endif return TRUE; error: diff --git a/xserver/glamor/glamor_egl.h b/xserver/glamor/glamor_egl.h index 6bb1185bf..2f7566b24 100644 --- a/xserver/glamor/glamor_egl.h +++ b/xserver/glamor/glamor_egl.h @@ -30,6 +30,7 @@ #define MESA_EGL_NO_X11_HEADERS #include <epoxy/gl.h> #include <epoxy/egl.h> +#include <glamor_egl_ext.h> /* * Create an EGLDisplay from a native display type. This is a little quirky diff --git a/xserver/glamor/glamor_egl_ext.h b/xserver/glamor/glamor_egl_ext.h new file mode 100644 index 000000000..436e52137 --- /dev/null +++ b/xserver/glamor/glamor_egl_ext.h @@ -0,0 +1,65 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 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. + */ +/* Extensions used by Glamor, copied from Mesa's eglmesaext.h, */ + +#ifndef GLAMOR_EGL_EXT_H +#define GLAMOR_EGL_EXT_H + +/* Define needed tokens from EGL_EXT_image_dma_buf_import extension + * here to avoid having to add ifdefs everywhere.*/ +#ifndef EGL_EXT_image_dma_buf_import +#define EGL_LINUX_DMA_BUF_EXT 0x3270 +#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 +#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 +#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 +#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 +#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 +#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 +#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 +#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 +#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#endif + +/* Define tokens from EGL_EXT_image_dma_buf_import_modifiers */ +#ifndef EGL_EXT_image_dma_buf_import_modifiers +#define EGL_EXT_image_dma_buf_import_modifiers 1 +#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440 +#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441 +#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442 +#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443 +#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444 +#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445 +#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446 +#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447 +#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448 +#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449 +#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers); +#endif + +#endif /* GLAMOR_EGL_EXT_H */ diff --git a/xserver/glamor/glamor_egl_stubs.c b/xserver/glamor/glamor_egl_stubs.c index 40f7fcc01..91ab9a7ae 100644 --- a/xserver/glamor/glamor_egl_stubs.c +++ b/xserver/glamor/glamor_egl_stubs.c @@ -36,10 +36,25 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) } int -glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, - PixmapPtr pixmap, - unsigned int tex, - Bool want_name, CARD16 *stride, CARD32 *size) +glamor_egl_fd_name_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, CARD32 *size) +{ + return -1; +} + + +int +glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *offsets, uint32_t *strides, + uint64_t *modifier) { return 0; } + +int +glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, + CARD16 *stride, CARD32 *size) +{ + return -1; +} diff --git a/xserver/glamor/glamor_eglmodule.c b/xserver/glamor/glamor_eglmodule.c index dd4664b22..326af3aa6 100644 --- a/xserver/glamor/glamor_eglmodule.c +++ b/xserver/glamor/glamor_eglmodule.c @@ -40,7 +40,7 @@ static XF86ModuleVersionInfo VersRec = { MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, - 1, 0, 0, /* version */ + 1, 0, 1, /* version */ ABI_CLASS_ANSIC, /* Only need the ansic layer */ ABI_ANSIC_VERSION, MOD_CLASS_NONE, diff --git a/xserver/glamor/glamor_fbo.c b/xserver/glamor/glamor_fbo.c index 9f1288c60..e8c4330b3 100644 --- a/xserver/glamor/glamor_fbo.c +++ b/xserver/glamor/glamor_fbo.c @@ -123,7 +123,10 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, int w, int h, GLenum format) { unsigned int tex; + GLenum iformat = format; + if (format == GL_RGB10_A2) + format = GL_RGBA; glamor_make_current(glamor_priv); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); @@ -132,7 +135,7 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, if (format == glamor_priv->one_channel_format && format == GL_RED) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED); glamor_priv->suppress_gl_out_of_memory_logging = true; - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, + glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, GL_UNSIGNED_BYTE, NULL); glamor_priv->suppress_gl_out_of_memory_logging = false; diff --git a/xserver/glamor/glamor_gradient.c b/xserver/glamor/glamor_gradient.c index f0b7d129c..eef078860 100644 --- a/xserver/glamor/glamor_gradient.c +++ b/xserver/glamor/glamor_gradient.c @@ -38,9 +38,7 @@ #define RADIAL_SMALL_STOPS (6 + 2) #define RADIAL_LARGE_STOPS (16 + 2) -#ifdef GLAMOR_GRADIENT_SHADER - -static const char * +static char * _glamor_create_getcolor_fs_source(ScreenPtr screen, int stops_count, int use_array) { @@ -312,7 +310,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, "}\n"\ "\n"\ "%s\n" /* fs_getcolor_source */ - const char *fs_getcolor_source; + char *fs_getcolor_source; glamor_priv = glamor_get_screen_private(screen); @@ -345,6 +343,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs); free(gradient_fs); + free(fs_getcolor_source); glAttachShader(gradient_prog, vs_prog); glAttachShader(gradient_prog, fs_prog); @@ -495,7 +494,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, "}\n"\ "\n"\ "%s" /* fs_getcolor_source */ - const char *fs_getcolor_source; + char *fs_getcolor_source; glamor_priv = glamor_get_screen_private(screen); @@ -524,6 +523,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs); free(gradient_fs); + free(fs_getcolor_source); glAttachShader(gradient_prog, vs_prog); glAttachShader(gradient_prog, fs_prog); @@ -1440,5 +1440,3 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); return NULL; } - -#endif /* End of GLAMOR_GRADIENT_SHADER */ diff --git a/xserver/glamor/glamor_image.c b/xserver/glamor/glamor_image.c index 315874995..453ef79ba 100644 --- a/xserver/glamor/glamor_image.c +++ b/xserver/glamor/glamor_image.c @@ -116,7 +116,7 @@ glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h, if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto bail; - if (format != ZPixmap || !glamor_pm_is_solid(drawable->depth, plane_mask)) + if (format != ZPixmap) goto bail; glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); @@ -128,6 +128,16 @@ glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h, drawable->x + off_x, drawable->y + off_y, -x, -y, (uint8_t *) d, byte_stride); + + if (!glamor_pm_is_solid(drawable->depth, plane_mask)) { + FbStip pm = fbReplicatePixel(plane_mask, drawable->bitsPerPixel); + FbStip *dst = (void *)d; + uint32_t dstStride = byte_stride / sizeof(FbStip); + + for (int i = 0; i < dstStride * h; i++) + dst[i] &= pm; + } + return TRUE; bail: return FALSE; diff --git a/xserver/glamor/glamor_priv.h b/xserver/glamor/glamor_priv.h index 27f95521d..7d9a7d4fb 100644 --- a/xserver/glamor/glamor_priv.h +++ b/xserver/glamor/glamor_priv.h @@ -38,7 +38,7 @@ #endif #include <epoxy/gl.h> -#if GLAMOR_HAS_GBM +#ifdef GLAMOR_HAS_GBM #define MESA_EGL_NO_X11_HEADERS #include <epoxy/egl.h> #endif @@ -163,7 +163,6 @@ enum glamor_gl_flavor { struct glamor_saved_procs { CloseScreenProcPtr close_screen; - CreateScreenResourcesProcPtr create_screen_resources; CreateGCProcPtr create_gc; CreatePixmapProcPtr create_pixmap; DestroyPixmapProcPtr destroy_pixmap; @@ -192,12 +191,12 @@ typedef struct glamor_screen_private { Bool has_map_buffer_range; Bool has_buffer_storage; Bool has_khr_debug; + Bool has_mesa_tile_raster_order; Bool has_nv_texture_barrier; Bool has_pack_subimage; Bool has_unpack_subimage; Bool has_rw_pbo; Bool use_quads; - Bool has_vertex_array_object; Bool has_dual_blend; Bool has_texture_swizzle; Bool is_core_profile; @@ -281,10 +280,8 @@ typedef struct glamor_screen_private { int linear_max_nstops; int radial_max_nstops; - int screen_fbo; struct glamor_saved_procs saved_procs; - char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; - int delayed_fallback_pending; + GetDrawableModifiersFuncPtr get_drawable_modifiers; int flags; ScreenPtr screen; int dri3_enabled; @@ -342,8 +339,9 @@ typedef struct glamor_pixmap_private { GLuint pbo; RegionRec prepare_region; Bool prepared; -#if GLAMOR_HAS_GBM +#ifdef GLAMOR_HAS_GBM EGLImageKHR image; + Bool used_modifiers; #endif /** block width of this large pixmap. */ int block_w; @@ -498,18 +496,11 @@ typedef struct { extern DevPrivateKeyRec glamor_gc_private_key; extern DevPrivateKeyRec glamor_screen_private_key; -static inline glamor_screen_private * -glamor_get_screen_private(ScreenPtr screen) -{ - return (glamor_screen_private *) - dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key); -} +extern glamor_screen_private * +glamor_get_screen_private(ScreenPtr screen); -static inline void -glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv) -{ - dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv); -} +extern void +glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv); static inline glamor_gc_private * glamor_get_gc_private(GCPtr gc) @@ -910,18 +901,8 @@ int glamor_xv_put_image(glamor_port_private *port_priv, void glamor_xv_core_init(ScreenPtr screen); void glamor_xv_render(glamor_port_private *port_priv); -#include"glamor_utils.h" - -/* Dynamic pixmap upload to texture if needed. - * Sometimes, the target is a gl texture pixmap/picture, - * but the source or mask is in cpu memory. In that case, - * upload the source/mask to gl texture and then avoid - * fallback the whole process to cpu. Most of the time, - * this will increase performance obviously. */ +#include "glamor_utils.h" -#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD -#define GLAMOR_GRADIENT_SHADER -#define GLAMOR_TEXTURED_LARGE_PIXMAP 1 #if 0 #define MAX_FBO_SIZE 32 /* For test purpose only. */ #endif diff --git a/xserver/glamor/glamor_program.c b/xserver/glamor/glamor_program.c index 23c102bc3..830deb38b 100644 --- a/xserver/glamor/glamor_program.c +++ b/xserver/glamor/glamor_program.c @@ -508,12 +508,13 @@ glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst) static Bool use_source_solid(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) { + PictSolidFill *solid = &src->pSourcePict->solidFill; + float color[4]; + glamor_get_rgba_from_color(&solid->fullcolor, color); glamor_set_blend(op, prog->alpha, dst); + glUniform4fv(prog->fg_uniform, 1, color); - glamor_set_color_depth(dst->pDrawable->pScreen, 32, - src->pSourcePict->solidFill.color, - prog->fg_uniform); return TRUE; } diff --git a/xserver/glamor/glamor_rects.c b/xserver/glamor/glamor_rects.c index cc029c8c0..6cbb040c1 100644 --- a/xserver/glamor/glamor_rects.c +++ b/xserver/glamor/glamor_rects.c @@ -53,6 +53,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, char *vbo_offset; int box_index; Bool ret = FALSE; + BoxRec bounds = glamor_no_rendering_bounds(); pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -60,6 +61,12 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, glamor_make_current(glamor_priv); + if (nrect < 100) { + bounds = glamor_start_rendering_bounds(); + for (int i = 0; i < nrect; i++) + glamor_bounds_union_rect(&bounds, &prect[i]); + } + if (glamor_priv->glsl_version >= 130) { prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_fill_rect_program, @@ -121,11 +128,22 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, goto bail; while (nbox--) { - glScissor(box->x1 + off_x, - box->y1 + off_y, - box->x2 - box->x1, - box->y2 - box->y1); + BoxRec scissor = { + .x1 = max(box->x1, bounds.x1 + drawable->x), + .y1 = max(box->y1, bounds.y1 + drawable->y), + .x2 = min(box->x2, bounds.x2 + drawable->x), + .y2 = min(box->y2, bounds.y2 + drawable->y), + }; + box++; + + if (scissor.x1 >= scissor.x2 || scissor.y1 >= scissor.y2) + continue; + + glScissor(scissor.x1 + off_x, + scissor.y1 + off_y, + scissor.x2 - scissor.x1, + scissor.y2 - scissor.y1); if (glamor_priv->glsl_version >= 130) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect); else { diff --git a/xserver/glamor/glamor_render.c b/xserver/glamor/glamor_render.c index a8b208101..d5737018f 100644 --- a/xserver/glamor/glamor_render.c +++ b/xserver/glamor/glamor_render.c @@ -762,21 +762,31 @@ glamor_set_normalize_tcoords_generic(PixmapPtr pixmap, /** * Returns whether the general composite path supports this picture * format for a pixmap that is permanently stored in an FBO (as - * opposed to the GLAMOR_PIXMAP_DYNAMIC_UPLOAD path). + * opposed to the dynamic upload path). * * We could support many more formats by using GL_ARB_texture_view to * parse the same bits as different formats. For now, we only support - * tweaking whether we sample the alpha bits of an a8r8g8b8, or just - * force them to 1. + * tweaking whether we sample the alpha bits, or just force them to 1. */ static Bool -glamor_render_format_is_supported(PictFormatShort format) +glamor_render_format_is_supported(PicturePtr picture) { - switch (format) { + PictFormatShort storage_format; + + /* Source-only pictures should always work */ + if (!picture->pDrawable) + return TRUE; + + storage_format = format_for_depth(picture->pDrawable->depth); + + switch (picture->format) { + case PICT_x2r10g10b10: + return storage_format == PICT_x2r10g10b10; case PICT_a8r8g8b8: case PICT_x8r8g8b8: + return storage_format == PICT_a8r8g8b8 || storage_format == PICT_x8r8g8b8; case PICT_a8: - return TRUE; + return storage_format == PICT_a8; default: return FALSE; } @@ -814,7 +824,7 @@ glamor_composite_choose_shader(CARD8 op, goto fail; } - if (!glamor_render_format_is_supported(dest->format)) { + if (!glamor_render_format_is_supported(dest)) { glamor_fallback("Unsupported dest picture format.\n"); goto fail; } @@ -828,13 +838,11 @@ glamor_composite_choose_shader(CARD8 op, source_solid_color[3] = 0.0; } else if (!source->pDrawable) { - if (source->pSourcePict->type == SourcePictTypeSolidFill) { + SourcePictPtr sp = source->pSourcePict; + if (sp->type == SourcePictTypeSolidFill) { key.source = SHADER_SOURCE_SOLID; - glamor_get_rgba_from_pixel(source->pSourcePict->solidFill.color, - &source_solid_color[0], - &source_solid_color[1], - &source_solid_color[2], - &source_solid_color[3], PICT_a8r8g8b8); + glamor_get_rgba_from_color(&sp->solidFill.fullcolor, + source_solid_color); } else goto fail; @@ -848,13 +856,11 @@ glamor_composite_choose_shader(CARD8 op, if (mask) { if (!mask->pDrawable) { - if (mask->pSourcePict->type == SourcePictTypeSolidFill) { + SourcePictPtr sp = mask->pSourcePict; + if (sp->type == SourcePictTypeSolidFill) { key.mask = SHADER_MASK_SOLID; - glamor_get_rgba_from_pixel - (mask->pSourcePict->solidFill.color, - &mask_solid_color[0], - &mask_solid_color[1], - &mask_solid_color[2], &mask_solid_color[3], PICT_a8r8g8b8); + glamor_get_rgba_from_color(&sp->solidFill.fullcolor, + mask_solid_color); } else goto fail; @@ -915,12 +921,7 @@ glamor_composite_choose_shader(CARD8 op, glamor_fallback("source == dest\n"); } if (source_pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) { -#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD source_needs_upload = TRUE; -#else - glamor_fallback("no texture in source\n"); - goto fail; -#endif } } @@ -931,16 +932,10 @@ glamor_composite_choose_shader(CARD8 op, goto fail; } if (mask_pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) { -#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD mask_needs_upload = TRUE; -#else - glamor_fallback("no texture in mask\n"); - goto fail; -#endif } } -#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD if (source_needs_upload && mask_needs_upload && source_pixmap == mask_pixmap) { @@ -992,7 +987,7 @@ glamor_composite_choose_shader(CARD8 op, goto fail; } } else { - if (source && !glamor_render_format_is_supported(source->format)) { + if (source && !glamor_render_format_is_supported(source)) { glamor_fallback("Unsupported source picture format.\n"); goto fail; } @@ -1004,13 +999,12 @@ glamor_composite_choose_shader(CARD8 op, goto fail; } } else if (mask) { - if (!glamor_render_format_is_supported(mask->format)) { + if (!glamor_render_format_is_supported(mask)) { glamor_fallback("Unsupported mask picture format.\n"); goto fail; } } } -#endif /* If the source and mask are two differently-formatted views of * the same pixmap bits, and the pixmap was already uploaded (so @@ -1198,6 +1192,29 @@ glamor_composite_with_shader(CARD8 op, nrect_max = MIN(nrect, GLAMOR_COMPOSITE_VBO_VERT_CNT / 4); + if (nrect < 100) { + BoxRec bounds = glamor_start_rendering_bounds(); + + for (int i = 0; i < nrect; i++) { + BoxRec box = { + .x1 = rects[i].x_dst, + .y1 = rects[i].y_dst, + .x2 = rects[i].x_dst + rects[i].width, + .y2 = rects[i].y_dst + rects[i].height, + }; + glamor_bounds_union_box(&bounds, &box); + } + + if (bounds.x1 >= bounds.x2 || bounds.y1 >= bounds.y2) + goto disable_va; + + glEnable(GL_SCISSOR_TEST); + glScissor(bounds.x1 + dest_x_off, + bounds.y1 + dest_y_off, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + } + while (nrect) { int mrect, rect_processed; int vb_stride; @@ -1279,6 +1296,8 @@ glamor_composite_with_shader(CARD8 op, } } + glDisable(GL_SCISSOR_TEST); +disable_va: glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); @@ -1318,7 +1337,6 @@ glamor_convert_gradient_picture(ScreenPtr screen, pFormat = PictureMatchFormat(screen, 32, format); } -#ifdef GLAMOR_GRADIENT_SHADER if (!source->pDrawable) { if (source->pSourcePict->type == SourcePictTypeLinear) { dst = glamor_generate_linear_gradient_picture(screen, @@ -1337,7 +1355,7 @@ glamor_convert_gradient_picture(ScreenPtr screen, return dst; } } -#endif + pixmap = glamor_create_pixmap(screen, width, height, diff --git a/xserver/glamor/glamor_transfer.c b/xserver/glamor/glamor_transfer.c index d788d06f4..ebb5101d1 100644 --- a/xserver/glamor/glamor_transfer.c +++ b/xserver/glamor/glamor_transfer.c @@ -33,6 +33,10 @@ glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type) *format = GL_BGRA; *type = GL_UNSIGNED_INT_8_8_8_8_REV; break; + case 30: + *format = GL_BGRA; + *type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; case 16: *format = GL_RGB; *type = GL_UNSIGNED_SHORT_5_6_5; diff --git a/xserver/glamor/glamor_utils.h b/xserver/glamor/glamor_utils.h index a35917c37..0d5674d63 100644 --- a/xserver/glamor/glamor_utils.h +++ b/xserver/glamor/glamor_utils.h @@ -562,10 +562,6 @@ (c)[1] = (float)y; \ } while(0) -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -#endif - #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) @@ -605,10 +601,8 @@ format_for_depth(int depth) default: case 24: return PICT_x8r8g8b8; -#if XORG_VERSION_CURRENT >= 10699900 case 30: return PICT_x2r10g10b10; -#endif case 32: return PICT_a8r8g8b8; } @@ -623,6 +617,9 @@ gl_iformat_for_pixmap(PixmapPtr pixmap) if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && ((pixmap)->drawable.depth == 1 || (pixmap)->drawable.depth == 8)) { return glamor_priv->one_channel_format; + } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && + (pixmap)->drawable.depth == 30) { + return GL_RGB10_A2; } else { return GL_RGBA; } @@ -670,7 +667,6 @@ glamor_get_rgba_from_pixel(CARD32 pixel, gshift = rbits; bshift = gshift + gbits; ashift = bshift + bbits; -#if XORG_VERSION_CURRENT >= 10699900 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { ashift = 0; @@ -679,7 +675,6 @@ glamor_get_rgba_from_pixel(CARD32 pixel, rshift = PICT_FORMAT_BPP(format) - (rbits + gbits + bbits); gshift = rshift + rbits; bshift = gshift + gbits; -#endif } else { return FALSE; @@ -711,6 +706,15 @@ glamor_get_rgba_from_pixel(CARD32 pixel, return TRUE; } +static inline void +glamor_get_rgba_from_color(const xRenderColor *color, float rgba[4]) +{ + rgba[0] = color->red / (float)UINT16_MAX; + rgba[1] = color->green / (float)UINT16_MAX; + rgba[2] = color->blue / (float)UINT16_MAX; + rgba[3] = color->alpha / (float)UINT16_MAX; +} + inline static Bool glamor_is_large_pixmap(PixmapPtr pixmap) { @@ -729,6 +733,50 @@ glamor_make_current(glamor_screen_private *glamor_priv) } } +static inline BoxRec +glamor_no_rendering_bounds(void) +{ + BoxRec bounds = { + .x1 = 0, + .y1 = 0, + .x2 = MAXSHORT, + .y2 = MAXSHORT, + }; + + return bounds; +} + +static inline BoxRec +glamor_start_rendering_bounds(void) +{ + BoxRec bounds = { + .x1 = MAXSHORT, + .y1 = MAXSHORT, + .x2 = 0, + .y2 = 0, + }; + + return bounds; +} + +static inline void +glamor_bounds_union_rect(BoxPtr bounds, xRectangle *rect) +{ + bounds->x1 = min(bounds->x1, rect->x); + bounds->y1 = min(bounds->y1, rect->y); + bounds->x2 = min(SHRT_MAX, max(bounds->x2, rect->x + rect->width)); + bounds->y2 = min(SHRT_MAX, max(bounds->y2, rect->y + rect->height)); +} + +static inline void +glamor_bounds_union_box(BoxPtr bounds, BoxPtr box) +{ + bounds->x1 = min(bounds->x1, box->x1); + bounds->y1 = min(bounds->y1, box->y1); + bounds->x2 = max(bounds->x2, box->x2); + bounds->y2 = max(bounds->y2, box->y2); +} + /** * Helper function for implementing draws with GL_QUADS on GLES2, * where we don't have them. diff --git a/xserver/glamor/glamor_vbo.c b/xserver/glamor/glamor_vbo.c index b8db0092b..734189fa2 100644 --- a/xserver/glamor/glamor_vbo.c +++ b/xserver/glamor/glamor_vbo.c @@ -128,7 +128,7 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset) if (glamor_priv->vbo_size < size) { glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size); free(glamor_priv->vb); - glamor_priv->vb = XNFalloc(glamor_priv->vbo_size); + glamor_priv->vb = xnfalloc(glamor_priv->vbo_size); } *vbo_offset = NULL; /* We point to the start of glamor_priv->vb every time, and @@ -174,11 +174,8 @@ glamor_init_vbo(ScreenPtr screen) glamor_make_current(glamor_priv); glGenBuffers(1, &glamor_priv->vbo); - if (glamor_priv->has_vertex_array_object) { - glGenVertexArrays(1, &glamor_priv->vao); - glBindVertexArray(glamor_priv->vao); - } else - glamor_priv->vao = 0; + glGenVertexArrays(1, &glamor_priv->vao); + glBindVertexArray(glamor_priv->vao); } void @@ -188,10 +185,8 @@ glamor_fini_vbo(ScreenPtr screen) glamor_make_current(glamor_priv); - if (glamor_priv->vao != 0) { - glDeleteVertexArrays(1, &glamor_priv->vao); - glamor_priv->vao = 0; - } + glDeleteVertexArrays(1, &glamor_priv->vao); + glamor_priv->vao = 0; if (!glamor_priv->has_map_buffer_range) free(glamor_priv->vb); } diff --git a/xserver/glamor/glamor_xv.c b/xserver/glamor/glamor_xv.c index e0375d7cd..62fc4fff5 100644 --- a/xserver/glamor/glamor_xv.c +++ b/xserver/glamor/glamor_xv.c @@ -210,6 +210,7 @@ glamor_xv_query_image_attributes(int id, switch (id) { case FOURCC_YV12: case FOURCC_I420: + *w = ALIGN(*w, 2); *h = ALIGN(*h, 2); size = ALIGN(*w, 4); if (pitches) |