diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2021-11-11 09:03:17 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2021-11-11 09:03:17 +0000 |
commit | 79250ad1e2b76f2ba5aa8d6dc0134c6c07ceac3a (patch) | |
tree | 6d31264b9d5ca7fc0d7c690ef6a3340917c949e4 /xserver/glamor/glamor.c | |
parent | 0c0a487400d29e7404b66758c41ad54ee01d46ee (diff) |
Update to xserver 21.1.0
Diffstat (limited to 'xserver/glamor/glamor.c')
-rw-r--r-- | xserver/glamor/glamor.c | 244 |
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); |