summaryrefslogtreecommitdiff
path: root/xserver/glamor
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2019-07-27 07:57:27 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2019-07-27 07:57:27 +0000
commitd4a0bed4b91da9de86c311c7fef9a8aa9a6f500c (patch)
treea1b439049dee87bc951e190db93f5bbe8b43b0b5 /xserver/glamor
parentb6bc775539a31f663f9e22ce3ccaf0aa96adf3b6 (diff)
Update to xserver 1.20.5. Tested by jsg@
Diffstat (limited to 'xserver/glamor')
-rw-r--r--xserver/glamor/Makefile.am1
-rw-r--r--xserver/glamor/Makefile.in15
-rw-r--r--xserver/glamor/glamor.c177
-rw-r--r--xserver/glamor/glamor.h108
-rw-r--r--xserver/glamor/glamor_copy.c148
-rw-r--r--xserver/glamor/glamor_core.c42
-rw-r--r--xserver/glamor/glamor_debug.h29
-rw-r--r--xserver/glamor/glamor_egl.c672
-rw-r--r--xserver/glamor/glamor_egl.h1
-rw-r--r--xserver/glamor/glamor_egl_ext.h65
-rw-r--r--xserver/glamor/glamor_egl_stubs.c23
-rw-r--r--xserver/glamor/glamor_eglmodule.c2
-rw-r--r--xserver/glamor/glamor_fbo.c5
-rw-r--r--xserver/glamor/glamor_gradient.c12
-rw-r--r--xserver/glamor/glamor_image.c12
-rw-r--r--xserver/glamor/glamor_priv.h39
-rw-r--r--xserver/glamor/glamor_program.c7
-rw-r--r--xserver/glamor/glamor_rects.c26
-rw-r--r--xserver/glamor/glamor_render.c88
-rw-r--r--xserver/glamor/glamor_transfer.c4
-rw-r--r--xserver/glamor/glamor_utils.h64
-rw-r--r--xserver/glamor/glamor_vbo.c15
-rw-r--r--xserver/glamor/glamor_xv.c1
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)