summaryrefslogtreecommitdiff
path: root/xserver/glamor/glamor.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2021-11-11 09:03:17 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2021-11-11 09:03:17 +0000
commit79250ad1e2b76f2ba5aa8d6dc0134c6c07ceac3a (patch)
tree6d31264b9d5ca7fc0d7c690ef6a3340917c949e4 /xserver/glamor/glamor.c
parent0c0a487400d29e7404b66758c41ad54ee01d46ee (diff)
Update to xserver 21.1.0
Diffstat (limited to 'xserver/glamor/glamor.c')
-rw-r--r--xserver/glamor/glamor.c244
1 files changed, 206 insertions, 38 deletions
diff --git a/xserver/glamor/glamor.c b/xserver/glamor/glamor.c
index 4409ca5c4..da2ea94ba 100644
--- a/xserver/glamor/glamor.c
+++ b/xserver/glamor/glamor.c
@@ -99,14 +99,13 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
glamor_init_pixmap_private_small(pixmap, pixmap_priv);
}
-_X_EXPORT void
+_X_EXPORT Bool
glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_pixmap_private *pixmap_priv;
glamor_screen_private *glamor_priv;
glamor_pixmap_fbo *fbo;
- GLenum format;
glamor_priv = glamor_get_screen_private(screen);
pixmap_priv = glamor_get_pixmap_private(pixmap);
@@ -116,16 +115,18 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
glamor_destroy_fbo(glamor_priv, fbo);
}
- format = gl_iformat_for_pixmap(pixmap);
- fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width,
- pixmap->drawable.height, format, tex, 0);
+ fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap,
+ pixmap->drawable.width,
+ pixmap->drawable.height, tex, 0);
if (fbo == NULL) {
ErrorF("XXX fail to create fbo.\n");
- return;
+ return FALSE;
}
glamor_pixmap_attach_fbo(pixmap, fbo);
+
+ return TRUE;
}
_X_EXPORT void
@@ -134,13 +135,15 @@ glamor_clear_pixmap(PixmapPtr pixmap)
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv;
glamor_pixmap_private *pixmap_priv;
+ const struct glamor_format *pixmap_format;
glamor_priv = glamor_get_screen_private(screen);
pixmap_priv = glamor_get_pixmap_private(pixmap);
+ pixmap_format = glamor_format_for_pixmap(pixmap);
assert(pixmap_priv->fbo != NULL);
- glamor_pixmap_clear_fbo(glamor_priv, pixmap_priv->fbo);
+ glamor_pixmap_clear_fbo(glamor_priv, pixmap_priv->fbo, pixmap_format);
}
uint32_t
@@ -184,8 +187,7 @@ glamor_bind_texture(glamor_screen_private *glamor_priv, GLenum texture,
/* Is the operand a GL_RED fbo?
*/
- if (glamor_fbo_red_is_alpha(glamor_priv, fbo)) {
-
+ if (fbo->is_red) {
/* If destination is also GL_RED, then preserve the bits in
* the R channel */
@@ -205,7 +207,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
glamor_pixmap_fbo *fbo = NULL;
int pitch;
- GLenum format;
if (w > 32767 || h > 32767)
return NullPixmap;
@@ -215,14 +216,14 @@ 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_priv->formats[depth].rendering_supported))
return fbCreatePixmap(screen, w, h, depth, usage);
else
pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
pixmap_priv = glamor_get_pixmap_private(pixmap);
- format = gl_iformat_for_pixmap(pixmap);
+ pixmap_priv->is_cbcr = (usage == GLAMOR_CREATE_FORMAT_CBCR);
pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
@@ -237,12 +238,12 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
glamor_check_fbo_size(glamor_priv, w, h))
{
glamor_init_pixmap_private_small(pixmap, pixmap_priv);
- fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
+ fbo = glamor_create_fbo(glamor_priv, pixmap, w, h, usage);
} else {
int tile_size = glamor_priv->max_fbo_size;
DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n",
pixmap, w, h, tile_size);
- fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage,
+ fbo = glamor_create_fbo_array(glamor_priv, pixmap, usage,
tile_size, tile_size, pixmap_priv);
}
@@ -413,6 +414,7 @@ glamor_debug_output_callback(GLenum source,
LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n",
screen->myNum, length, message);
+ xorg_backtrace();
}
/**
@@ -422,7 +424,8 @@ glamor_debug_output_callback(GLenum source,
static void
glamor_setup_debug_output(ScreenPtr screen)
{
- if (!epoxy_has_gl_extension("GL_ARB_debug_output"))
+ if (!epoxy_has_gl_extension("GL_KHR_debug") &&
+ !epoxy_has_gl_extension("GL_ARB_debug_output"))
return;
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
@@ -443,6 +446,172 @@ glamor_setup_debug_output(ScreenPtr screen)
glEnable(GL_DEBUG_OUTPUT);
}
+const struct glamor_format *
+glamor_format_for_pixmap(PixmapPtr pixmap)
+{
+ ScreenPtr pScreen = pixmap->drawable.pScreen;
+ glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
+ glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+ if (pixmap_priv->is_cbcr)
+ return &glamor_priv->cbcr_format;
+ else
+ return &glamor_priv->formats[pixmap->drawable.depth];
+}
+
+static void
+glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format,
+ GLenum internalformat, GLenum format, GLenum type,
+ Bool rendering_supported)
+{
+ glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+ struct glamor_format *f = &glamor_priv->formats[depth];
+
+ /* If we're trying to run on GLES, make sure that we get the read
+ * formats that we're expecting, since glamor_transfer relies on
+ * them matching to get data back out. To avoid this limitation, we
+ * would need to have a more general glReadPixels() path in
+ * glamor_transfer that re-encoded the bits to the pixel format that
+ * we intended after.
+ *
+ * Note that we can't just create a pixmap because we're in
+ * screeninit.
+ */
+ if (rendering_supported && glamor_priv->is_gles) {
+ unsigned fbo, tex;
+ int read_format, read_type;
+ GLenum status;
+
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0,
+ format, type, NULL);
+
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex, 0);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ ErrorF("glamor: Test fbo for depth %d incomplete. "
+ "Falling back to software.\n", depth);
+ glDeleteTextures(1, &tex);
+ glDeleteFramebuffers(1, &fbo);
+ return;
+ }
+
+ glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format);
+ glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type);
+
+ glDeleteTextures(1, &tex);
+ glDeleteFramebuffers(1, &fbo);
+
+ if (format != read_format || type != read_type) {
+ ErrorF("glamor: Implementation returned 0x%x/0x%x read format/type "
+ "for depth %d, expected 0x%x/0x%x. "
+ "Falling back to software.\n",
+ read_format, read_type, depth, format, type);
+ return;
+ }
+ }
+
+ f->depth = depth;
+ f->render_format = render_format;
+ f->internalformat = internalformat;
+ f->format = format;
+ f->type = type;
+ f->rendering_supported = rendering_supported;
+}
+
+/* Set up the GL format/types that glamor will use for the various depths
+ *
+ * X11's pixel data doesn't have channels, but to store our data in GL
+ * we have to pick some sort of format to move X11 pixel data in and
+ * out with in glamor_transfer.c. For X11 core operations, other than
+ * GL logic ops (non-GXcopy GC ops) what the driver chooses internally
+ * doesn't matter as long as it doesn't drop any bits (we expect them
+ * to generally expand, if anything). For Render, we can expect
+ * clients to tend to render with PictFormats matching our channel
+ * layouts here since ultimately X11 pixels tend to end up on the
+ * screen. The render implementation will fall back to fb if the
+ * channels don't match.
+ *
+ * Note that these formats don't affect what glamor_egl.c or
+ * Xwayland's EGL layer choose for surfaces exposed through DRI or
+ * scanout. For now, those layers need to match what we're choosing
+ * here, or channels will end up swizzled around. Similarly, the
+ * driver's visual masks also need to match what we're doing here.
+ */
+static void
+glamor_setup_formats(ScreenPtr screen)
+{
+ glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+ /* Prefer r8 textures since they're required by GLES3 and core,
+ * only falling back to a8 if we can't do them.
+ */
+ if (glamor_priv->is_gles || epoxy_has_gl_extension("GL_ARB_texture_rg")) {
+ glamor_add_format(screen, 1, PICT_a1,
+ GL_R8, GL_RED, GL_UNSIGNED_BYTE, FALSE);
+ glamor_add_format(screen, 8, PICT_a8,
+ GL_R8, GL_RED, GL_UNSIGNED_BYTE, TRUE);
+ } else {
+ glamor_add_format(screen, 1, PICT_a1,
+ GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, FALSE);
+ glamor_add_format(screen, 8, PICT_a8,
+ GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, TRUE);
+ }
+
+ if (glamor_priv->is_gles) {
+ /* For 15bpp, GLES supports format/type RGBA/5551, rather than
+ * bgra/1555_rev. GL_EXT_bgra lets the impl say the color
+ * read format/type is bgra/1555 even if we had to create it
+ * with rgba/5551, with Mesa does. That means we can't use
+ * the same format/type for TexSubImage and readpixels.
+ *
+ * Instead, just store 16 bits using the trusted 565 path, and
+ * disable render accel for now.
+ */
+ glamor_add_format(screen, 15, PICT_x1r5g5b5,
+ GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, TRUE);
+ } else {
+ glamor_add_format(screen, 15, PICT_x1r5g5b5,
+ GL_RGBA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, TRUE);
+ }
+
+ glamor_add_format(screen, 16, PICT_r5g6b5,
+ GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, TRUE);
+
+ if (glamor_priv->is_gles) {
+ assert(X_BYTE_ORDER == X_LITTLE_ENDIAN);
+ glamor_add_format(screen, 24, PICT_x8b8g8r8,
+ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, TRUE);
+ glamor_add_format(screen, 32, PICT_a8b8g8r8,
+ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, TRUE);
+ } else {
+ glamor_add_format(screen, 24, PICT_x8r8g8b8,
+ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE);
+ glamor_add_format(screen, 32, PICT_a8r8g8b8,
+ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE);
+ }
+
+ if (glamor_priv->is_gles) {
+ glamor_add_format(screen, 30, PICT_x2b10g10r10,
+ GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE);
+ } else {
+ glamor_add_format(screen, 30, PICT_x2r10g10b10,
+ GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE);
+ }
+
+ glamor_priv->cbcr_format.depth = 16;
+ glamor_priv->cbcr_format.internalformat = GL_RG8;
+ glamor_priv->cbcr_format.format = GL_RG;
+ glamor_priv->cbcr_format.type = GL_UNSIGNED_BYTE;
+ glamor_priv->cbcr_format.rendering_supported = TRUE;
+}
+
/** Set up glamor for an already-configured GL context. */
Bool
glamor_init(ScreenPtr screen, unsigned int flags)
@@ -508,10 +677,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
glamor_make_current(glamor_priv);
- if (epoxy_is_desktop_gl())
- glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP;
- else
- glamor_priv->gl_flavor = GLAMOR_GL_ES2;
+ if (!epoxy_is_desktop_gl())
+ glamor_priv->is_gles = TRUE;
gl_version = epoxy_gl_version();
@@ -543,7 +710,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
}
glamor_priv->glsl_version = glsl_major * 100 + glsl_minor;
- if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
+ if (glamor_priv->is_gles) {
/* Force us back to the base version of our programs on an ES
* context, anyway. Basically glamor only uses desktop 1.20
* or 1.30 currently. 1.30's new features are also present in
@@ -567,7 +734,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
* have support for it, with most of the ones lacking it being on
* Windows with Intel 4-series (G45) graphics or older.
*/
- if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+ if (!glamor_priv->is_gles) {
if (gl_version < 21) {
ErrorF("Require OpenGL version 2.1 or later.\n");
goto fail;
@@ -586,7 +753,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
* have instanced arrays, but this is not always the case.
* etnaviv offers GLSL 140 with OpenGL 2.1.
*/
- if (glamor_priv->glsl_version >= 130 &&
+ if (glamor_glsl_has_ints(glamor_priv) &&
!epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
glamor_priv->glsl_version = 120;
} else {
@@ -612,8 +779,12 @@ glamor_init(ScreenPtr screen, unsigned int flags)
goto fail;
}
+ if (!glamor_priv->is_gles && glamor_priv->glsl_version == 120 &&
+ epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
+ glamor_priv->use_gpu_shader4 = epoxy_has_gl_extension("GL_EXT_gpu_shader4");
+
glamor_priv->has_rw_pbo = FALSE;
- if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
+ if (!glamor_priv->is_gles)
glamor_priv->has_rw_pbo = TRUE;
glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug");
@@ -631,22 +802,25 @@ glamor_init(ScreenPtr screen, unsigned int flags)
glamor_priv->has_nv_texture_barrier =
epoxy_has_gl_extension("GL_NV_texture_barrier");
glamor_priv->has_unpack_subimage =
- glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP ||
+ !glamor_priv->is_gles ||
epoxy_gl_version() >= 30 ||
epoxy_has_gl_extension("GL_EXT_unpack_subimage");
glamor_priv->has_pack_subimage =
- glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP ||
+ !glamor_priv->is_gles ||
epoxy_gl_version() >= 30 ||
epoxy_has_gl_extension("GL_NV_pack_subimage");
glamor_priv->has_dual_blend =
- glamor_priv->glsl_version >= 130 &&
+ glamor_glsl_has_ints(glamor_priv) &&
epoxy_has_gl_extension("GL_ARB_blend_func_extended");
+ glamor_priv->has_clear_texture =
+ epoxy_gl_version() >= 44 ||
+ epoxy_has_gl_extension("GL_ARB_clear_texture");
glamor_priv->can_copyplane = (gl_version >= 30);
glamor_setup_debug_output(screen);
- glamor_priv->use_quads = (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) &&
+ glamor_priv->use_quads = !glamor_priv->is_gles &&
!glamor_priv->is_core_profile;
/* Driver-specific hack: Avoid using GL_QUADS on VC4, where
@@ -669,13 +843,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
glamor_priv->has_texture_swizzle =
(epoxy_has_gl_extension("GL_ARB_texture_swizzle") ||
- (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && gl_version >= 30));
+ (glamor_priv->is_gles && gl_version >= 30));
- glamor_priv->one_channel_format = GL_ALPHA;
- if (epoxy_has_gl_extension("GL_ARB_texture_rg") &&
- glamor_priv->has_texture_swizzle) {
- glamor_priv->one_channel_format = GL_RED;
- }
+ glamor_setup_formats(screen);
glamor_set_debug_level(&glamor_debug_level);
@@ -860,8 +1030,7 @@ _glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
switch (pixmap_priv->type) {
case GLAMOR_TEXTURE_DRM:
case GLAMOR_TEXTURE_ONLY:
- if (!glamor_pixmap_ensure_fbo(pixmap, pixmap->drawable.depth == 30 ?
- GL_RGB10_A2 : GL_RGBA, 0))
+ if (!glamor_pixmap_ensure_fbo(pixmap, 0))
return 0;
if (modifier) {
@@ -916,7 +1085,7 @@ glamor_shareable_fd_from_pixmap(ScreenPtr screen,
int ret;
/*
- * The actual difference between a sharable and non sharable buffer
+ * The actual difference between a shareable and non-shareable buffer
* is decided 4 call levels deep in glamor_make_pixmap_exportable()
* based on pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED
* 2 of those calls are also exported API, so we cannot just add a flag.
@@ -937,8 +1106,7 @@ 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, pixmap->drawable.depth == 30 ?
- GL_RGB10_A2 : GL_RGBA, 0))
+ if (!glamor_pixmap_ensure_fbo(pixmap, 0))
return -1;
return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen,
pixmap, stride, size);