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 | |
parent | 0c0a487400d29e7404b66758c41ad54ee01d46ee (diff) |
Update to xserver 21.1.0
Diffstat (limited to 'xserver/glamor')
-rw-r--r-- | xserver/glamor/Makefile.in | 38 | ||||
-rw-r--r-- | xserver/glamor/glamor.c | 244 | ||||
-rw-r--r-- | xserver/glamor/glamor.h | 5 | ||||
-rw-r--r-- | xserver/glamor/glamor_composite_glyphs.c | 15 | ||||
-rw-r--r-- | xserver/glamor/glamor_egl.c | 96 | ||||
-rw-r--r-- | xserver/glamor/glamor_fbo.c | 55 | ||||
-rw-r--r-- | xserver/glamor/glamor_font.c | 4 | ||||
-rw-r--r-- | xserver/glamor/glamor_gradient.c | 6 | ||||
-rw-r--r-- | xserver/glamor/glamor_largepixmap.c | 2 | ||||
-rw-r--r-- | xserver/glamor/glamor_picture.c | 31 | ||||
-rw-r--r-- | xserver/glamor/glamor_pixmap.c | 2 | ||||
-rw-r--r-- | xserver/glamor/glamor_priv.h | 71 | ||||
-rw-r--r-- | xserver/glamor/glamor_program.c | 19 | ||||
-rw-r--r-- | xserver/glamor/glamor_rects.c | 6 | ||||
-rw-r--r-- | xserver/glamor/glamor_render.c | 24 | ||||
-rw-r--r-- | xserver/glamor/glamor_spans.c | 20 | ||||
-rw-r--r-- | xserver/glamor/glamor_transfer.c | 50 | ||||
-rw-r--r-- | xserver/glamor/glamor_transfer.h | 3 | ||||
-rw-r--r-- | xserver/glamor/glamor_transform.c | 7 | ||||
-rw-r--r-- | xserver/glamor/glamor_utils.h | 63 | ||||
-rw-r--r-- | xserver/glamor/glamor_vbo.c | 2 | ||||
-rw-r--r-- | xserver/glamor/glamor_xv.c | 182 |
22 files changed, 598 insertions, 347 deletions
diff --git a/xserver/glamor/Makefile.in b/xserver/glamor/Makefile.in index 516ec52b0..4fa7f3a6e 100644 --- a/xserver/glamor/Makefile.in +++ b/xserver/glamor/Makefile.in @@ -72,7 +72,6 @@ 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/xwayland-config.h \ $(top_builddir)/include/version-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @@ -205,8 +204,6 @@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BASE_CFLAGS = @BASE_CFLAGS@ BASE_FONT_PATH = @BASE_FONT_PATH@ -BUILD_DATE = @BUILD_DATE@ -BUILD_TIME = @BUILD_TIME@ BUNDLE_ID_PREFIX = @BUNDLE_ID_PREFIX@ BUNDLE_VERSION = @BUNDLE_VERSION@ BUNDLE_VERSION_STRING = @BUNDLE_VERSION_STRING@ @@ -238,14 +235,6 @@ DIX_CFLAGS = @DIX_CFLAGS@ DIX_LIB = @DIX_LIB@ DLLTOOL = @DLLTOOL@ DLOPEN_LIBS = @DLOPEN_LIBS@ -DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@ -DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@ -DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@ -DMXMODULES_LIBS = @DMXMODULES_LIBS@ -DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@ -DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ -DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ -DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ DOT = @DOT@ DOXYGEN = @DOXYGEN@ DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ @@ -319,6 +308,8 @@ LIBSHA1_LIBS = @LIBSHA1_LIBS@ LIBTOOL = @LIBTOOL@ LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBXCVT_CFLAGS = @LIBXCVT_CFLAGS@ +LIBXCVT_LIBS = @LIBXCVT_LIBS@ LIB_MAN_DIR = @LIB_MAN_DIR@ LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ LIPO = @LIPO@ @@ -371,7 +362,6 @@ 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@ @@ -395,29 +385,13 @@ 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@ -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@ -XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@ -XDMX_CFLAGS = @XDMX_CFLAGS@ -XDMX_LIBS = @XDMX_LIBS@ -XDMX_SYS_LIBS = @XDMX_SYS_LIBS@ XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ XEPHYR_INCS = @XEPHYR_INCS@ XEPHYR_LIBS = @XEPHYR_LIBS@ @@ -455,8 +429,6 @@ XPBPROXY_LIBS = @XPBPROXY_LIBS@ XQUARTZ_LIBS = @XQUARTZ_LIBS@ XQUARTZ_SPARKLE = @XQUARTZ_SPARKLE@ XQUARTZ_SPARKLE_FEED_URL = @XQUARTZ_SPARKLE_FEED_URL@ -XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ -XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@ XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@ XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@ @@ -467,14 +439,8 @@ XSHMFENCE_CFLAGS = @XSHMFENCE_CFLAGS@ XSHMFENCE_LIBS = @XSHMFENCE_LIBS@ XSLTPROC = @XSLTPROC@ XSL_STYLESHEET = @XSL_STYLESHEET@ -XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@ -XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@ XVFB_LIBS = @XVFB_LIBS@ XVFB_SYS_LIBS = @XVFB_SYS_LIBS@ -XWAYLANDMODULES_CFLAGS = @XWAYLANDMODULES_CFLAGS@ -XWAYLANDMODULES_LIBS = @XWAYLANDMODULES_LIBS@ -XWAYLAND_LIBS = @XWAYLAND_LIBS@ -XWAYLAND_SYS_LIBS = @XWAYLAND_SYS_LIBS@ XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@ XWINMODULES_LIBS = @XWINMODULES_LIBS@ XWIN_LIBS = @XWIN_LIBS@ 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); diff --git a/xserver/glamor/glamor.h b/xserver/glamor/glamor.h index be04bf858..31157471d 100644 --- a/xserver/glamor/glamor.h +++ b/xserver/glamor/glamor.h @@ -110,7 +110,7 @@ extern _X_EXPORT Bool glamor_close_screen(ScreenPtr screen); extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap); -extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, +extern _X_EXPORT Bool glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex); extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap, @@ -129,6 +129,7 @@ extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap); #define GLAMOR_CREATE_FBO_NO_FBO 0x103 #define GLAMOR_CREATE_NO_LARGE 0x105 #define GLAMOR_CREATE_PIXMAP_NO_TEXTURE 0x106 +#define GLAMOR_CREATE_FORMAT_CBCR 0x107 /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo). * @@ -343,7 +344,7 @@ extern _X_EXPORT void glamor_set_drawable_modifiers_func(ScreenPtr screen, * @scrn: Current screen info pointer. * @fd: Current drm fd. * - * This function creates and intialize EGL contexts. + * This function creates and initializes EGL contexts. * Should be called from DDX's preInit function. * Return TRUE if success, otherwise return FALSE. * */ diff --git a/xserver/glamor/glamor_composite_glyphs.c b/xserver/glamor/glamor_composite_glyphs.c index b65127477..147e3bb31 100644 --- a/xserver/glamor/glamor_composite_glyphs.c +++ b/xserver/glamor/glamor_composite_glyphs.c @@ -208,11 +208,6 @@ static const glamor_facet glamor_facet_composite_glyphs_120 = { .locations = glamor_program_location_atlas, }; -static inline Bool -glamor_glyph_use_130(glamor_screen_private *glamor_priv) { - return glamor_priv->glsl_version >= 130; -} - static Bool glamor_glyphs_init_facet(ScreenPtr screen) { @@ -274,7 +269,7 @@ glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst, box->y2 - box->y1); box++; - if (glamor_glyph_use_130(glamor_priv)) + if (glamor_glsl_has_ints(glamor_priv)) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph); else glamor_glDrawArrays_GL_QUADS(glamor_priv, nglyph); @@ -287,7 +282,7 @@ glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst, glDisable(GL_SCISSOR_TEST); - if (glamor_glyph_use_130(glamor_priv)) { + if (glamor_glsl_has_ints(glamor_priv)) { glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0); glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); } @@ -305,7 +300,7 @@ glamor_glyph_start(ScreenPtr screen, int count) /* Set up the vertex buffers for the font and destination */ - if (glamor_glyph_use_130(glamor_priv)) { + if (glamor_glsl_has_ints(glamor_priv)) { v = glamor_get_vbo_space(screen, count * (6 * sizeof (GLshort)), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); @@ -439,7 +434,7 @@ glamor_composite_glyphs(CARD8 op, /* First glyph in the current atlas? */ if (_X_UNLIKELY(glyphs_queued == 0)) { - if (glamor_glyph_use_130(glamor_priv)) + if (glamor_glsl_has_ints(glamor_priv)) prog = glamor_setup_program_render(op, src, glyph_pict, dst, glyphs_program, &glamor_facet_composite_glyphs_130, @@ -458,7 +453,7 @@ glamor_composite_glyphs(CARD8 op, */ glyphs_queued++; - if (_X_LIKELY(glamor_glyph_use_130(glamor_priv))) { + if (_X_LIKELY(glamor_glsl_has_ints(glamor_priv))) { v[0] = x - glyph->info.x; v[1] = y - glyph->info.y; v[2] = glyph_draw->width; diff --git a/xserver/glamor/glamor_egl.c b/xserver/glamor/glamor_egl.c index 78c2aaef7..8028add63 100644 --- a/xserver/glamor/glamor_egl.c +++ b/xserver/glamor/glamor_egl.c @@ -233,7 +233,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, glamor_make_current(glamor_priv); image = eglCreateImageKHR(glamor_egl->display, - glamor_egl->context, + EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, bo, NULL); if (image == EGL_NO_IMAGE_KHR) { glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); @@ -280,18 +280,30 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) (modifiers_ok || !pixmap_priv->used_modifiers)) return TRUE; - if (pixmap->drawable.bitsPerPixel != 32) { + switch (pixmap->drawable.depth) { + case 30: + format = GBM_FORMAT_ARGB2101010; + break; + case 32: + case 24: + format = GBM_FORMAT_ARGB8888; + break; + case 16: + format = GBM_FORMAT_RGB565; + break; + case 15: + format = GBM_FORMAT_ARGB1555; + break; + case 8: + format = GBM_FORMAT_R8; + break; + default: xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to make %dbpp pixmap exportable\n", - pixmap->drawable.bitsPerPixel); + "Failed to make %d depth, %dbpp pixmap exportable\n", + pixmap->drawable.depth, pixmap->drawable.bitsPerPixel); return FALSE; } - 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; @@ -925,6 +937,8 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) { struct glamor_egl_screen_private *glamor_egl; const GLubyte *renderer; + EGLConfig egl_config; + int n; glamor_egl = calloc(sizeof(*glamor_egl), 1); if (glamor_egl == NULL) @@ -992,6 +1006,22 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) config_attribs); } + if (glamor_egl->context != EGL_NO_CONTEXT) { + if (!eglMakeCurrent(glamor_egl->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make GL context current\n"); + goto error; + } + + if (epoxy_gl_version() < 21) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "glamor: Ignoring GL < 2.1, falling back to GLES.\n"); + eglDestroyContext(glamor_egl->display, glamor_egl->context); + glamor_egl->context = EGL_NO_CONTEXT; + } + } + if (glamor_egl->context == EGL_NO_CONTEXT) { static const EGLint config_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, @@ -1003,21 +1033,28 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) goto error; } + if (!eglChooseConfig(glamor_egl->display, NULL, &egl_config, 1, &n)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "glamor: No acceptable EGL configs found\n"); + goto error; + } + glamor_egl->context = eglCreateContext(glamor_egl->display, - NULL, EGL_NO_CONTEXT, + egl_config, 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, - EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to make EGL context current\n"); - goto error; + 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, + EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make GLES2 context current\n"); + goto error; + } } renderer = glGetString(GL_RENDERER); @@ -1027,9 +1064,14 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) goto error; } if (strstr((const char *)renderer, "llvmpipe")) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Refusing to try glamor on llvmpipe\n"); - goto error; + if (scrn->confScreen->num_gpu_devices) + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Allowing glamor on llvmpipe for PRIME\n"); + else { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Refusing to try glamor on llvmpipe\n"); + goto error; + } } /* @@ -1052,9 +1094,9 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) "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"); + if (xf86Info.debug != NULL) + glamor_egl->dmabuf_capable = !!strstr(xf86Info.debug, + "dmabuf_capable"); else glamor_egl->dmabuf_capable = FALSE; } diff --git a/xserver/glamor/glamor_fbo.c b/xserver/glamor/glamor_fbo.c index f939a6c2f..e045d247e 100644 --- a/xserver/glamor/glamor_fbo.c +++ b/xserver/glamor/glamor_fbo.c @@ -95,8 +95,9 @@ glamor_pixmap_ensure_fb(glamor_screen_private *glamor_priv, glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, GLint tex, int flag) + PixmapPtr pixmap, int w, int h, GLint tex, int flag) { + const struct glamor_format *f = glamor_format_for_pixmap(pixmap); glamor_pixmap_fbo *fbo; fbo = calloc(1, sizeof(*fbo)); @@ -106,7 +107,7 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, fbo->tex = tex; fbo->width = w; fbo->height = h; - fbo->format = format; + fbo->is_red = f->format == GL_RED; if (flag != GLAMOR_CREATE_FBO_NO_FBO) { if (glamor_pixmap_ensure_fb(glamor_priv, fbo) != 0) { @@ -120,23 +121,21 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, static int _glamor_create_tex(glamor_screen_private *glamor_priv, - int w, int h, GLenum format) + PixmapPtr pixmap, int w, int h) { + const struct glamor_format *f = glamor_format_for_pixmap(pixmap); 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); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (format == glamor_priv->one_channel_format && format == GL_RED) + if (f->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, iformat, w, h, 0, - format, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, f->internalformat, w, h, 0, + f->format, f->type, NULL); glamor_priv->suppress_gl_out_of_memory_logging = false; if (glGetError() == GL_OUT_OF_MEMORY) { @@ -156,14 +155,15 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, int flag) + PixmapPtr pixmap, int w, int h, int flag) { - GLint tex = _glamor_create_tex(glamor_priv, w, h, format); + GLint tex = _glamor_create_tex(glamor_priv, pixmap, w, h); if (!tex) /* Texture creation failed due to GL_OUT_OF_MEMORY */ return NULL; - return glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag); + return glamor_create_fbo_from_tex(glamor_priv, pixmap, w, h, + tex, flag); } /** @@ -172,10 +172,12 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, */ glamor_pixmap_fbo * glamor_create_fbo_array(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, int flag, + PixmapPtr pixmap, int flag, int block_w, int block_h, glamor_pixmap_private *priv) { + int w = pixmap->drawable.width; + int h = pixmap->drawable.height; int block_wcnt; int block_hcnt; glamor_pixmap_fbo **fbo_array; @@ -215,8 +217,8 @@ glamor_create_fbo_array(glamor_screen_private *glamor_priv, box_array[i * block_wcnt + j].x2 - box_array[i * block_wcnt + j].x1; fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv, + pixmap, fbo_w, fbo_h, - format, GLAMOR_CREATE_PIXMAP_FIXUP); if (fbo_array[i * block_wcnt + j] == NULL) goto cleanup; @@ -240,15 +242,22 @@ glamor_create_fbo_array(glamor_screen_private *glamor_priv, } void -glamor_pixmap_clear_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo) +glamor_pixmap_clear_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo, + const struct glamor_format *pixmap_format) { glamor_make_current(glamor_priv); assert(fbo->fb != 0 && fbo->tex != 0); - glamor_set_destination_pixmap_fbo(glamor_priv, fbo, 0, 0, fbo->width, fbo->height); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); + if (glamor_priv->has_clear_texture) { + glClearTexImage(fbo->tex, 0, pixmap_format->format, pixmap_format->type, NULL); + } + else { + glamor_set_destination_pixmap_fbo(glamor_priv, fbo, 0, 0, fbo->width, fbo->height); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } } glamor_pixmap_fbo * @@ -314,7 +323,7 @@ glamor_pixmap_destroy_fbo(PixmapPtr pixmap) } Bool -glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) +glamor_pixmap_ensure_fbo(PixmapPtr pixmap, int flag) { glamor_screen_private *glamor_priv; glamor_pixmap_private *pixmap_priv; @@ -324,8 +333,8 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv->fbo == NULL) { - fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, - pixmap->drawable.height, format, flag); + fbo = glamor_create_fbo(glamor_priv, pixmap, pixmap->drawable.width, + pixmap->drawable.height, flag); if (fbo == NULL) return FALSE; @@ -335,8 +344,8 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) /* We do have a fbo, but it may lack of fb or tex. */ if (!pixmap_priv->fbo->tex) pixmap_priv->fbo->tex = - _glamor_create_tex(glamor_priv, pixmap->drawable.width, - pixmap->drawable.height, format); + _glamor_create_tex(glamor_priv, pixmap, pixmap->drawable.width, + pixmap->drawable.height); if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0) if (glamor_pixmap_ensure_fb(glamor_priv, pixmap_priv->fbo) != 0) diff --git a/xserver/glamor/glamor_font.c b/xserver/glamor/glamor_font.c index 9199a355b..c60fa787b 100644 --- a/xserver/glamor/glamor_font.c +++ b/xserver/glamor/glamor_font.c @@ -47,7 +47,7 @@ glamor_font_get(ScreenPtr screen, FontPtr font) unsigned long count; char *bits; - if (glamor_priv->glsl_version < 130) + if (!glamor_glsl_has_ints(glamor_priv)) return NULL; privates = FontGetPrivate(font, glamor_font_private_index); @@ -210,7 +210,7 @@ glamor_font_init(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - if (glamor_priv->glsl_version < 130) + if (!glamor_glsl_has_ints(glamor_priv)) return TRUE; if (glamor_font_generation != serverGeneration) { diff --git a/xserver/glamor/glamor_gradient.c b/xserver/glamor/glamor_gradient.c index eef078860..7e5d5cca9 100644 --- a/xserver/glamor/glamor_gradient.c +++ b/xserver/glamor/glamor_gradient.c @@ -204,7 +204,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, * Refer to pixman radial gradient. * * The problem is given the two circles of c1 and c2 with the radius of r1 and - * r1, we need to caculate the t, which is used to do interpolate with stops, + * r1, we need to calculate the t, which is used to do interpolate with stops, * using the fomula: * length((1-t)*c1 + t*c2 - p) = (1-t)*r1 + t*r2 * expand the fomula with xy coond, get the following: @@ -428,11 +428,11 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, * | * * step 1: compute the distance of p, pt1 and pt2 in the slope direction. - * Caculate the distance on Y axis first and multiply cos_val to + * Calculate the distance on Y axis first and multiply cos_val to * get the value on slope direction(pd, p1d and p2d represent the * distance of p, pt1, and pt2 respectively). * - * step 2: caculate the percentage of (pd - p1d)/(p2d - p1d). + * step 2: calculate the percentage of (pd - p1d)/(p2d - p1d). * If (pd - p1d) > (p2d - p1d) or < 0, then sub or add (p2d - p1d) * to make it in the range of [0, (p2d - p1d)]. * diff --git a/xserver/glamor/glamor_largepixmap.c b/xserver/glamor/glamor_largepixmap.c index f9adb93bc..57760f8d3 100644 --- a/xserver/glamor/glamor_largepixmap.c +++ b/xserver/glamor/glamor_largepixmap.c @@ -744,7 +744,7 @@ glamor_compute_transform_clipped_regions(PixmapPtr pixmap, /* * As transform and repeatpad mode. - * We may get a clipped result which in multipe regions. + * We may get a clipped result which in multiple regions. * It's not easy to do a 2nd round clipping just as we do * without transform/repeatPad. As it's not easy to reverse * the 2nd round clipping result with a transform/repeatPad mode, diff --git a/xserver/glamor/glamor_picture.c b/xserver/glamor/glamor_picture.c index 685d8d618..33b3bebd9 100644 --- a/xserver/glamor/glamor_picture.c +++ b/xserver/glamor/glamor_picture.c @@ -83,14 +83,14 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, switch (format) { case PICT_a1: - *tex_format = glamor_priv->one_channel_format; + *tex_format = glamor_priv->formats[1].format; *tex_type = GL_UNSIGNED_BYTE; *temp_format = PICT_a8; break; case PICT_b8g8r8x8: case PICT_b8g8r8a8: - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_INT_8_8_8_8; } else { @@ -109,7 +109,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, case PICT_x8r8g8b8: case PICT_a8r8g8b8: - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; } else { @@ -128,7 +128,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, case PICT_x8b8g8r8: case PICT_a8b8g8r8: *tex_format = GL_RGBA; - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; } else { *tex_format = GL_RGBA; @@ -141,7 +141,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, case PICT_x2r10g10b10: case PICT_a2r10g10b10: - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; } else { @@ -151,7 +151,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, case PICT_x2b10g10r10: case PICT_a2b10g10r10: - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; } else { @@ -165,7 +165,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, break; case PICT_b5g6r5: *tex_format = GL_RGB; - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV; } else { *tex_type = GL_UNSIGNED_SHORT_5_6_5; @@ -177,7 +177,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, case PICT_x1b5g5r5: case PICT_a1b5g5r5: *tex_format = GL_RGBA; - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; } else { return FALSE; @@ -186,7 +186,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, case PICT_x1r5g5b5: case PICT_a1r5g5b5: - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; } else { @@ -195,13 +195,13 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, break; case PICT_a8: - *tex_format = glamor_priv->one_channel_format; + *tex_format = glamor_priv->formats[8].format; *tex_type = GL_UNSIGNED_BYTE; break; case PICT_x4r4g4b4: case PICT_a4r4g4b4: - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; } else { @@ -213,7 +213,7 @@ glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, case PICT_x4b4g4r4: case PICT_a4b4g4r4: - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (!glamor_priv->is_gles) { *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; } else { @@ -286,6 +286,7 @@ glamor_upload_picture_to_texture(PicturePtr picture) Bool ret = TRUE; Bool needs_swizzle; pixman_image_t *converted_image = NULL; + const struct glamor_format *f = glamor_format_for_pixmap(pixmap); assert(glamor_pixmap_is_memory(pixmap)); assert(!pixmap_priv->fbo); @@ -335,12 +336,12 @@ glamor_upload_picture_to_texture(PicturePtr picture) stride = pixman_image_get_stride(converted_image); } - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - iformat = gl_iformat_for_pixmap(pixmap); + if (!glamor_priv->is_gles) + iformat = f->internalformat; else iformat = format; - if (!glamor_pixmap_ensure_fbo(pixmap, iformat, GLAMOR_CREATE_FBO_NO_FBO)) { + if (!glamor_pixmap_ensure_fbo(pixmap, GLAMOR_CREATE_FBO_NO_FBO)) { ret = FALSE; goto fail; } diff --git a/xserver/glamor/glamor_pixmap.c b/xserver/glamor/glamor_pixmap.c index 166bde509..9aa169cdc 100644 --- a/xserver/glamor/glamor_pixmap.c +++ b/xserver/glamor/glamor_pixmap.c @@ -124,7 +124,7 @@ glamor_set_alu(ScreenPtr screen, unsigned char alu) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + if (glamor_priv->is_gles) { if (alu != GXcopy) return FALSE; else diff --git a/xserver/glamor/glamor_priv.h b/xserver/glamor/glamor_priv.h index 4353a99f1..028a6d374 100644 --- a/xserver/glamor/glamor_priv.h +++ b/xserver/glamor/glamor_priv.h @@ -155,13 +155,28 @@ enum gradient_shader { struct glamor_screen_private; struct glamor_pixmap_private; -enum glamor_gl_flavor { - GLAMOR_GL_DESKTOP, // OPENGL API - GLAMOR_GL_ES2 // OPENGL ES2.0 API -}; - #define GLAMOR_COMPOSITE_VBO_VERT_CNT (64*1024) +struct glamor_format { + /** X Server's "depth" value */ + int depth; + /** GL internalformat for creating textures of this type */ + GLenum internalformat; + /** GL format transferring pixels in/out of textures of this type. */ + GLenum format; + /** GL type transferring pixels in/out of textures of this type. */ + GLenum type; + /* Render PICT_* matching GL's channel layout for pixels + * transferred using format/type. + */ + CARD32 render_format; + /** + * Whether rendering is supported in GL at all (i.e. without pixel data conversion + * just before upload) + */ + Bool rendering_supported; +}; + struct glamor_saved_procs { CloseScreenProcPtr close_screen; CreateGCProcPtr create_gc; @@ -185,7 +200,7 @@ struct glamor_saved_procs { }; typedef struct glamor_screen_private { - enum glamor_gl_flavor gl_flavor; + Bool is_gles; int glsl_version; Bool has_pack_invert; Bool has_fbo_blit; @@ -199,12 +214,20 @@ typedef struct glamor_screen_private { Bool has_rw_pbo; Bool use_quads; Bool has_dual_blend; + Bool has_clear_texture; Bool has_texture_swizzle; Bool is_core_profile; Bool can_copyplane; + Bool use_gpu_shader4; int max_fbo_size; - GLuint one_channel_format; + /** + * Stores information about supported formats. Note, that this list contains all + * supported pixel formats, including these that are not supported on GL side + * directly, but are converted to another format instead. + */ + struct glamor_format formats[33]; + struct glamor_format cbcr_format; /* glamor point shader */ glamor_program point_prog; @@ -317,8 +340,7 @@ typedef struct glamor_pixmap_fbo { GLuint fb; /**< GL FBO name */ int width; /**< width in pixels */ int height; /**< height in pixels */ - GLenum format; /**< GL format used to create the texture. */ - GLenum type; /**< GL type used to create the texture. */ + Bool is_red; } glamor_pixmap_fbo; typedef struct glamor_pixmap_clipped_regions { @@ -380,6 +402,8 @@ typedef struct glamor_pixmap_private { * names. */ glamor_pixmap_fbo **fbo_array; + + Bool is_cbcr; } glamor_pixmap_private; extern DevPrivateKeyRec glamor_pixmap_private_key; @@ -530,16 +554,19 @@ glamor_pixmap_fbo *glamor_pixmap_detach_fbo(glamor_pixmap_private * pixmap_priv); void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo); glamor_pixmap_fbo *glamor_create_fbo_from_tex(glamor_screen_private * - glamor_priv, int w, int h, - GLenum format, GLint tex, + glamor_priv, PixmapPtr pixmap, + int w, int h, GLint tex, int flag); -glamor_pixmap_fbo *glamor_create_fbo(glamor_screen_private *glamor_priv, int w, - int h, GLenum format, int flag); +glamor_pixmap_fbo *glamor_create_fbo(glamor_screen_private *glamor_priv, + PixmapPtr pixmap, int w, int h, int flag); void glamor_destroy_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo); void glamor_pixmap_destroy_fbo(PixmapPtr pixmap); Bool glamor_pixmap_fbo_fixup(ScreenPtr screen, PixmapPtr pixmap); -void glamor_pixmap_clear_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo); +void glamor_pixmap_clear_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo, + const struct glamor_format *pixmap_format); + +const struct glamor_format *glamor_format_for_pixmap(PixmapPtr pixmap); /* Return whether 'picture' is alpha-only */ static inline Bool glamor_picture_is_alpha(PicturePtr picture) @@ -547,21 +574,13 @@ static inline Bool glamor_picture_is_alpha(PicturePtr picture) return picture->format == PICT_a1 || picture->format == PICT_a8; } -/* Return whether 'fbo' is storing alpha bits in the red channel */ -static inline Bool -glamor_fbo_red_is_alpha(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo) -{ - /* True when the format is GL_RED (that can only happen when our one channel format is GL_RED */ - return fbo->format == GL_RED; -} - /* Return whether 'picture' is storing alpha bits in the red channel */ static inline Bool glamor_picture_red_is_alpha(PicturePtr picture) { /* True when the picture is alpha only and the screen is using GL_RED for alpha pictures */ return glamor_picture_is_alpha(picture) && - glamor_get_screen_private(picture->pDrawable->pScreen)->one_channel_format == GL_RED; + glamor_get_screen_private(picture->pDrawable->pScreen)->formats[8].format == GL_RED; } void glamor_bind_texture(glamor_screen_private *glamor_priv, @@ -570,7 +589,7 @@ void glamor_bind_texture(glamor_screen_private *glamor_priv, Bool destination_red); glamor_pixmap_fbo *glamor_create_fbo_array(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, + PixmapPtr pixmap, int flag, int block_w, int block_h, glamor_pixmap_private *); @@ -680,7 +699,7 @@ glamor_put_vbo_space(ScreenPtr screen); * the fbo has valid texture and attach to a valid fb. * If the fbo already has a valid glfbo then do nothing. */ -Bool glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag); +Bool glamor_pixmap_ensure_fbo(PixmapPtr pixmap, int flag); glamor_pixmap_clipped_regions * glamor_compute_clipped_regions(PixmapPtr pixmap, @@ -902,7 +921,7 @@ int glamor_xv_put_image(glamor_port_private *port_priv, Bool sync, RegionPtr clipBoxes); void glamor_xv_core_init(ScreenPtr screen); -void glamor_xv_render(glamor_port_private *port_priv); +void glamor_xv_render(glamor_port_private *port_priv, int id); #include "glamor_utils.h" diff --git a/xserver/glamor/glamor_program.c b/xserver/glamor/glamor_program.c index 830deb38b..c51577fc3 100644 --- a/xserver/glamor/glamor_program.c +++ b/xserver/glamor/glamor_program.c @@ -187,6 +187,7 @@ fs_location_vars(glamor_program_location locations) static const char vs_template[] = "%s" /* version */ + "%s" /* exts */ "%s" /* defines */ "%s" /* prim vs_vars */ "%s" /* fill vs_vars */ @@ -199,6 +200,7 @@ static const char vs_template[] = static const char fs_template[] = "%s" /* version */ + "%s" /* exts */ GLAMOR_DEFAULT_PRECISION "%s" /* defines */ "%s" /* prim fs_vars */ @@ -262,6 +264,7 @@ glamor_build_program(ScreenPtr screen, char *fs_prog_string; GLint fs_prog, vs_prog; + Bool gpu_shader4 = FALSE; if (!fill) fill = &facet_null_fill; @@ -270,8 +273,14 @@ glamor_build_program(ScreenPtr screen, flags |= fill->flags; version = MAX(version, fill->version); - if (version > glamor_priv->glsl_version) - goto fail; + if (version > glamor_priv->glsl_version) { + if (version == 130 && !glamor_priv->use_gpu_shader4) + goto fail; + else { + version = 120; + gpu_shader4 = TRUE; + } + } vs_vars = vs_location_vars(locations); fs_vars = fs_location_vars(locations); @@ -291,6 +300,7 @@ glamor_build_program(ScreenPtr screen, if (asprintf(&vs_prog_string, vs_template, str(version_string), + gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n" : "", str(defines), str(prim->vs_vars), str(fill->vs_vars), @@ -302,6 +312,7 @@ glamor_build_program(ScreenPtr screen, if (asprintf(&fs_prog_string, fs_template, str(version_string), + gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n#define texelFetch texelFetch2D\n#define uint unsigned int\n" : "", str(defines), str(prim->fs_vars), str(fill->fs_vars), @@ -372,6 +383,8 @@ fail: glDeleteProgram(prog->prog); prog->prog = 0; } + free(vs_prog_string); + free(fs_prog_string); free(version_string); free(fs_vars); free(vs_vars); @@ -459,7 +472,7 @@ glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst) break; } - if (glamor_priv->gl_flavor != GLAMOR_GL_ES2) + if (!glamor_priv->is_gles) glDisable(GL_COLOR_LOGIC_OP); if (op == PictOpSrc) diff --git a/xserver/glamor/glamor_rects.c b/xserver/glamor/glamor_rects.c index ae4fe8bcc..8cdad64e4 100644 --- a/xserver/glamor/glamor_rects.c +++ b/xserver/glamor/glamor_rects.c @@ -69,7 +69,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, glamor_bounds_union_rect(&bounds, &prect[i]); } - if (glamor_priv->glsl_version >= 130) { + if (glamor_glsl_has_ints(glamor_priv)) { prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_fill_rect_program, &glamor_facet_polyfillrect_130); @@ -151,7 +151,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, scissor.y1 + off_y, scissor.x2 - scissor.x1, scissor.y2 - scissor.y1); - if (glamor_priv->glsl_version >= 130) + if (glamor_glsl_has_ints(glamor_priv)) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect); else { glamor_glDrawArrays_GL_QUADS(glamor_priv, nrect); @@ -163,7 +163,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, bail: glDisable(GL_SCISSOR_TEST); - if (glamor_priv->glsl_version >= 130) { + if (glamor_glsl_has_ints(glamor_priv)) { glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); diff --git a/xserver/glamor/glamor_render.c b/xserver/glamor/glamor_render.c index d5737018f..2af65bf93 100644 --- a/xserver/glamor/glamor_render.c +++ b/xserver/glamor/glamor_render.c @@ -529,7 +529,7 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, * sometimes get zero bits in the R channel, which is harmless. */ glamor_bind_texture(glamor_priv, GL_TEXTURE0 + unit, fbo, - glamor_fbo_red_is_alpha(glamor_priv, dest_priv->fbo)); + dest_priv->fbo->is_red); repeat_type = picture->repeatType; switch (picture->repeatType) { case RepeatNone: @@ -772,23 +772,31 @@ static Bool glamor_render_format_is_supported(PicturePtr picture) { PictFormatShort storage_format; + glamor_screen_private *glamor_priv; + struct glamor_format *f; /* Source-only pictures should always work */ if (!picture->pDrawable) return TRUE; - storage_format = format_for_depth(picture->pDrawable->depth); + glamor_priv = glamor_get_screen_private(picture->pDrawable->pScreen); + f = &glamor_priv->formats[picture->pDrawable->depth]; + + if (!f->rendering_supported) + return FALSE; + + storage_format = f->render_format; switch (picture->format) { - case PICT_x2r10g10b10: + case PICT_a2r10g10b10: return storage_format == PICT_x2r10g10b10; case PICT_a8r8g8b8: case PICT_x8r8g8b8: return storage_format == PICT_a8r8g8b8 || storage_format == PICT_x8r8g8b8; - case PICT_a8: - return storage_format == PICT_a8; + case PICT_a1r5g5b5: + return storage_format == PICT_x1r5g5b5; default: - return FALSE; + return picture->format == storage_format; } } @@ -898,7 +906,7 @@ glamor_composite_choose_shader(CARD8 op, } if (dest_pixmap->drawable.bitsPerPixel <= 8 && - glamor_priv->one_channel_format == GL_RED) { + glamor_priv->formats[8].format == GL_RED) { key.dest_swizzle = SHADER_DEST_SWIZZLE_ALPHA_TO_RED; } else { key.dest_swizzle = SHADER_DEST_SWIZZLE_DEFAULT; @@ -1091,7 +1099,7 @@ glamor_composite_set_shader_blend(glamor_screen_private *glamor_priv, } } - if (glamor_priv->gl_flavor != GLAMOR_GL_ES2) + if (!glamor_priv->is_gles) glDisable(GL_COLOR_LOGIC_OP); if (op_info->source_blend == GL_ONE && op_info->dest_blend == GL_ZERO) { diff --git a/xserver/glamor/glamor_spans.c b/xserver/glamor/glamor_spans.c index b3c028d67..00a019c7b 100644 --- a/xserver/glamor/glamor_spans.c +++ b/xserver/glamor/glamor_spans.c @@ -64,7 +64,7 @@ glamor_fill_spans_gl(DrawablePtr drawable, glamor_make_current(glamor_priv); - if (glamor_priv->glsl_version >= 130) { + if (glamor_glsl_has_ints(glamor_priv)) { prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program, &glamor_facet_fillspans_130); @@ -134,7 +134,7 @@ glamor_fill_spans_gl(DrawablePtr drawable, box->x2 - box->x1, box->y2 - box->y1); box++; - if (glamor_priv->glsl_version >= 130) + if (glamor_glsl_has_ints(glamor_priv)) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n); else { glamor_glDrawArrays_GL_QUADS(glamor_priv, n); @@ -146,7 +146,7 @@ glamor_fill_spans_gl(DrawablePtr drawable, bail: glDisable(GL_SCISSOR_TEST); - if (glamor_priv->glsl_version >= 130) + if (glamor_glsl_has_ints(glamor_priv)) glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); @@ -187,9 +187,8 @@ glamor_get_spans_gl(DrawablePtr drawable, int wmax, int box_index; int n; char *d; - GLenum type; - GLenum format; int off_x, off_y; + const struct glamor_format *f = glamor_format_for_pixmap(pixmap); pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -197,8 +196,6 @@ glamor_get_spans_gl(DrawablePtr drawable, int wmax, glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); - glamor_format_for_pixmap(pixmap, &format, &type); - glamor_make_current(glamor_priv); glamor_pixmap_loop(pixmap_priv, box_index) { @@ -234,7 +231,8 @@ glamor_get_spans_gl(DrawablePtr drawable, int wmax, if (y >= box->y2) continue; - glReadPixels(x1 - box->x1, y - box->y1, x2 - x1, 1, format, type, l); + glReadPixels(x1 - box->x1, y - box->y1, x2 - x1, 1, + f->format, f->type, l); } } @@ -269,11 +267,10 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv; + const struct glamor_format *f = glamor_format_for_pixmap(pixmap); int box_index; int n; char *s; - GLenum type; - GLenum format; int off_x, off_y; pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -287,7 +284,6 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, goto bail; glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); - glamor_format_for_pixmap(pixmap, &format, &type); glamor_make_current(glamor_priv); @@ -348,7 +344,7 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, glTexSubImage2D(GL_TEXTURE_2D, 0, x1 - box->x1, y1 - box->y1, x2 - x1, 1, - format, type, + f->format, f->type, l); } s += PixmapBytePad(w, drawable->depth); diff --git a/xserver/glamor/glamor_transfer.c b/xserver/glamor/glamor_transfer.c index ebb5101d1..e706e0fb4 100644 --- a/xserver/glamor/glamor_transfer.c +++ b/xserver/glamor/glamor_transfer.c @@ -23,38 +23,6 @@ #include "glamor_priv.h" #include "glamor_transfer.h" -/* XXX a kludge for now */ -void -glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type) -{ - switch (pixmap->drawable.depth) { - case 24: - case 32: - *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; - break; - case 15: - *format = GL_BGRA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - case 8: - *format = glamor_get_screen_private(pixmap->drawable.pScreen)->one_channel_format; - *type = GL_UNSIGNED_BYTE; - break; - default: - FatalError("Invalid pixmap depth %d\n", pixmap->drawable.depth); - break; - } -} - /* * Write a region of bits into a pixmap */ @@ -69,10 +37,7 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); int box_index; int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3; - GLenum type; - GLenum format; - - glamor_format_for_pixmap(pixmap, &format, &type); + const struct glamor_format *f = glamor_format_for_pixmap(pixmap); glamor_make_current(glamor_priv); @@ -110,14 +75,14 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, glTexSubImage2D(GL_TEXTURE_2D, 0, x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, - format, type, + f->format, f->type, bits + ofs); } else { for (; y1 < y2; y1++, ofs += byte_stride) glTexSubImage2D(GL_TEXTURE_2D, 0, x1 - box->x1, y1 - box->y1, x2 - x1, 1, - format, type, + f->format, f->type, bits + ofs); } } @@ -172,10 +137,7 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); int box_index; int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3; - GLenum type; - GLenum format; - - glamor_format_for_pixmap(pixmap, &format, &type); + const struct glamor_format *f = glamor_format_for_pixmap(pixmap); glamor_make_current(glamor_priv); @@ -210,10 +172,10 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, if (glamor_priv->has_pack_subimage || x2 - x1 == byte_stride / bytes_per_pixel) { - glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits + ofs); + glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, f->format, f->type, bits + ofs); } else { for (; y1 < y2; y1++, ofs += byte_stride) - glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs); + glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, f->format, f->type, bits + ofs); } } } diff --git a/xserver/glamor/glamor_transfer.h b/xserver/glamor/glamor_transfer.h index de8186a70..a6137b3ff 100644 --- a/xserver/glamor/glamor_transfer.h +++ b/xserver/glamor/glamor_transfer.h @@ -24,9 +24,6 @@ #define _GLAMOR_TRANSFER_H_ void -glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type); - -void glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, int dx_src, int dy_src, int dx_dst, int dy_dst, diff --git a/xserver/glamor/glamor_transform.c b/xserver/glamor/glamor_transform.c index 2d5a634a8..11a08f7f6 100644 --- a/xserver/glamor/glamor_transform.c +++ b/xserver/glamor/glamor_transform.c @@ -121,10 +121,9 @@ glamor_set_color_depth(ScreenPtr pScreen, glamor_get_rgba_from_pixel(pixel, &color[0], &color[1], &color[2], &color[3], - format_for_depth(depth)); + glamor_priv->formats[depth].render_format); - if ((depth == 1 || depth == 8) && - glamor_priv->one_channel_format == GL_RED) + if ((depth <= 8) && glamor_priv->formats[8].format == GL_RED) color[0] = color[3]; glUniform4fv(uniform, 1, color); @@ -159,7 +158,7 @@ glamor_set_solid(PixmapPtr pixmap, return FALSE; } } - glamor_set_color(pixmap, gc->fgPixel, uniform); + glamor_set_color(pixmap, pixel, uniform); return TRUE; } diff --git a/xserver/glamor/glamor_utils.h b/xserver/glamor/glamor_utils.h index 0d5674d63..93a933eed 100644 --- a/xserver/glamor/glamor_utils.h +++ b/xserver/glamor/glamor_utils.h @@ -570,67 +570,8 @@ && (_w_) <= _glamor_->max_fbo_size \ && (_h_) <= _glamor_->max_fbo_size) -/* For 1bpp pixmap, we don't store it as texture. */ -#define glamor_check_pixmap_fbo_depth(_depth_) ( \ - _depth_ == 8 \ - || _depth_ == 15 \ - || _depth_ == 16 \ - || _depth_ == 24 \ - || _depth_ == 30 \ - || _depth_ == 32) - #define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL) -/** - * Borrow from uxa. - */ -static inline CARD32 -format_for_depth(int depth) -{ - switch (depth) { - case 1: - return PICT_a1; - case 4: - return PICT_a4; - case 8: - return PICT_a8; - case 15: - return PICT_x1r5g5b5; - case 16: - return PICT_r5g6b5; - default: - case 24: - return PICT_x8r8g8b8; - case 30: - return PICT_x2r10g10b10; - case 32: - return PICT_a8r8g8b8; - } -} - -static inline GLenum -gl_iformat_for_pixmap(PixmapPtr pixmap) -{ - glamor_screen_private *glamor_priv = - glamor_get_screen_private((pixmap)->drawable.pScreen); - - 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; - } -} - -static inline CARD32 -format_for_pixmap(PixmapPtr pixmap) -{ - return format_for_depth((pixmap)->drawable.depth); -} - #define REVERT_NONE 0 #define REVERT_NORMAL 1 #define REVERT_UPLOADING_A1 3 @@ -791,5 +732,9 @@ glamor_glDrawArrays_GL_QUADS(glamor_screen_private *glamor_priv, unsigned count) } } +static inline Bool +glamor_glsl_has_ints(glamor_screen_private *glamor_priv) { + return glamor_priv->glsl_version >= 130 || glamor_priv->use_gpu_shader4; +} #endif diff --git a/xserver/glamor/glamor_vbo.c b/xserver/glamor/glamor_vbo.c index 734189fa2..000c3e827 100644 --- a/xserver/glamor/glamor_vbo.c +++ b/xserver/glamor/glamor_vbo.c @@ -24,7 +24,7 @@ /** * @file glamor_vbo.c * - * Helpers for managing streamed vertex bufffers used in glamor. + * Helpers for managing streamed vertex buffers used in glamor. */ #include "glamor_priv.h" diff --git a/xserver/glamor/glamor_xv.c b/xserver/glamor/glamor_xv.c index 62fc4fff5..dbb490599 100644 --- a/xserver/glamor/glamor_xv.c +++ b/xserver/glamor/glamor_xv.c @@ -41,7 +41,7 @@ #include "glamor_transfer.h" #include <X11/extensions/Xv.h> -#include "../hw/xfree86/common/fourcc.h" +#include <fourcc.h> /* Reference color space transform data */ typedef struct tagREF_TRANSFORM { float RefLuma; @@ -59,8 +59,40 @@ typedef struct tagREF_TRANSFORM { #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0) #define RTFHue(a) (((a)*3.1416)/1000.0) -static const glamor_facet glamor_facet_xv_planar = { - .name = "xv_planar", +static const glamor_facet glamor_facet_xv_planar_2 = { + .name = "xv_planar_2", + + .version = 120, + + .source_name = "v_texcoord0", + .vs_vars = ("attribute vec2 position;\n" + "attribute vec2 v_texcoord0;\n" + "varying vec2 tcs;\n"), + .vs_exec = (GLAMOR_POS(gl_Position, position) + " tcs = v_texcoord0;\n"), + + .fs_vars = ("uniform sampler2D y_sampler;\n" + "uniform sampler2D u_sampler;\n" + "uniform vec4 offsetyco;\n" + "uniform vec4 ucogamma;\n" + "uniform vec4 vco;\n" + "varying vec2 tcs;\n"), + .fs_exec = ( + " float sample;\n" + " vec2 sample_uv;\n" + " vec4 temp1;\n" + " sample = texture2D(y_sampler, tcs).w;\n" + " temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n" + " sample_uv = texture2D(u_sampler, tcs).xy;\n" + " temp1.xyz = ucogamma.xyz * vec3(sample_uv.x) + temp1.xyz;\n" + " temp1.xyz = clamp(vco.xyz * vec3(sample_uv.y) + temp1.xyz, 0.0, 1.0);\n" + " temp1.w = 1.0;\n" + " gl_FragColor = temp1;\n" + ), +}; + +static const glamor_facet glamor_facet_xv_planar_3 = { + .name = "xv_planar_3", .version = 120, @@ -110,26 +142,50 @@ Atom glamorBrightness, glamorContrast, glamorSaturation, glamorHue, XvImageRec glamor_xv_images[] = { XVIMAGE_YV12, XVIMAGE_I420, + XVIMAGE_NV12 }; int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images); static void -glamor_init_xv_shader(ScreenPtr screen) +glamor_init_xv_shader(ScreenPtr screen, int id) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); GLint sampler_loc; + const glamor_facet *glamor_facet_xv_planar = NULL; + + switch (id) { + case FOURCC_YV12: + case FOURCC_I420: + glamor_facet_xv_planar = &glamor_facet_xv_planar_3; + break; + case FOURCC_NV12: + glamor_facet_xv_planar = &glamor_facet_xv_planar_2; + break; + default: + break; + } glamor_build_program(screen, &glamor_priv->xv_prog, - &glamor_facet_xv_planar, NULL, NULL, NULL); + glamor_facet_xv_planar, NULL, NULL, NULL); glUseProgram(glamor_priv->xv_prog.prog); sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "y_sampler"); glUniform1i(sampler_loc, 0); sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "u_sampler"); glUniform1i(sampler_loc, 1); - sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "v_sampler"); - glUniform1i(sampler_loc, 2); + + switch (id) { + case FOURCC_YV12: + case FOURCC_I420: + sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "v_sampler"); + glUniform1i(sampler_loc, 2); + break; + case FOURCC_NV12: + break; + default: + break; + } } @@ -227,6 +283,21 @@ glamor_xv_query_image_attributes(int id, offsets[2] = size; size += tmp; break; + case FOURCC_NV12: + *w = ALIGN(*w, 2); + *h = ALIGN(*h, 2); + size = ALIGN(*w, 4); + if (pitches) + pitches[0] = size; + size *= *h; + if (offsets) + offsets[1] = offsets[2] = size; + tmp = ALIGN(*w, 4); + if (pitches) + pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + break; } return size; } @@ -240,7 +311,7 @@ static REF_TRANSFORM trans[2] = { }; void -glamor_xv_render(glamor_port_private *port_priv) +glamor_xv_render(glamor_port_private *port_priv, int id) { ScreenPtr screen = port_priv->pPixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -264,7 +335,7 @@ glamor_xv_render(glamor_port_private *port_priv) int dst_box_index; if (!glamor_priv->xv_prog.prog) - glamor_init_xv_shader(screen); + glamor_init_xv_shader(screen, id); cont = RTFContrast(port_priv->contrast); bright = RTFBrightness(port_priv->brightness); @@ -293,6 +364,8 @@ glamor_xv_render(glamor_port_private *port_priv) glamor_get_pixmap_private(port_priv->src_pix[i]); pixmap_priv_get_scale(src_pixmap_priv[i], &src_xscale[i], &src_yscale[i]); + } else { + src_pixmap_priv[i] = NULL; } } glamor_make_current(glamor_priv); @@ -319,12 +392,21 @@ glamor_xv_render(glamor_port_private *port_priv) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->fbo->tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + switch (id) { + case FOURCC_YV12: + case FOURCC_I420: + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->fbo->tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + break; + case FOURCC_NV12: + break; + default: + break; + } glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); @@ -336,7 +418,7 @@ glamor_xv_render(glamor_port_private *port_priv) /* Set up a single primitive covering the area being drawn. We'll * clip it to port_priv->clip using GL scissors instead of just * emitting a GL_QUAD per box, because this way we hopefully avoid - * diagonal tearing between the two trangles used to rasterize a + * diagonal tearing between the two triangles used to rasterize a * GL_QUAD. */ i = 0; @@ -417,6 +499,7 @@ glamor_xv_put_image(glamor_port_private *port_priv, RegionPtr clipBoxes) { ScreenPtr pScreen = pDrawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); int srcPitch, srcPitch2; int top, nlines; int s2offset, s3offset, tmp; @@ -425,9 +508,16 @@ glamor_xv_put_image(glamor_port_private *port_priv, s2offset = s3offset = srcPitch2 = 0; if (!port_priv->src_pix[0] || - (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) { + (width != port_priv->src_pix_w || height != port_priv->src_pix_h) || + (port_priv->src_pix[2] && id == FOURCC_NV12) || + (!port_priv->src_pix[2] && id != FOURCC_NV12)) { int i; + if (glamor_priv->xv_prog.prog) { + glDeleteProgram(glamor_priv->xv_prog.prog); + glamor_priv->xv_prog.prog = 0; + } + for (i = 0; i < 3; i++) if (port_priv->src_pix[i]) glamor_destroy_pixmap(port_priv->src_pix[i]); @@ -435,17 +525,34 @@ glamor_xv_put_image(glamor_port_private *port_priv, port_priv->src_pix[0] = glamor_create_pixmap(pScreen, width, height, 8, GLAMOR_CREATE_FBO_NO_FBO); - port_priv->src_pix[1] = - glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, - GLAMOR_CREATE_FBO_NO_FBO); - port_priv->src_pix[2] = - glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, - GLAMOR_CREATE_FBO_NO_FBO); + + switch (id) { + case FOURCC_YV12: + case FOURCC_I420: + port_priv->src_pix[1] = + glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, + GLAMOR_CREATE_FBO_NO_FBO); + port_priv->src_pix[2] = + glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, + GLAMOR_CREATE_FBO_NO_FBO); + if (!port_priv->src_pix[2]) + return BadAlloc; + break; + case FOURCC_NV12: + port_priv->src_pix[1] = + glamor_create_pixmap(pScreen, width >> 1, height >> 1, 16, + GLAMOR_CREATE_FBO_NO_FBO | + GLAMOR_CREATE_FORMAT_CBCR); + port_priv->src_pix[2] = NULL; + break; + default: + return BadMatch; + } + port_priv->src_pix_w = width; port_priv->src_pix_h = height; - if (!port_priv->src_pix[0] || !port_priv->src_pix[1] || - !port_priv->src_pix[2]) + if (!port_priv->src_pix[0] || !port_priv->src_pix[1]) return BadAlloc; } @@ -489,6 +596,29 @@ glamor_xv_put_image(glamor_port_private *port_priv, 0, 0, 0, 0, buf + s3offset, srcPitch2); break; + case FOURCC_NV12: + srcPitch = ALIGN(width, 4); + s2offset = srcPitch * height; + s2offset += ((top >> 1) * srcPitch); + + full_box.x1 = 0; + full_box.y1 = 0; + full_box.x2 = width; + full_box.y2 = nlines; + + half_box.x1 = 0; + half_box.y1 = 0; + half_box.x2 = width; + half_box.y2 = (nlines + 1) >> 1; + + glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1, + 0, 0, 0, 0, + buf + (top * srcPitch), srcPitch); + + glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1, + 0, 0, 0, 0, + buf + s2offset, srcPitch); + break; default: return BadMatch; } @@ -511,7 +641,7 @@ glamor_xv_put_image(glamor_port_private *port_priv, port_priv->w = width; port_priv->h = height; port_priv->pDraw = pDrawable; - glamor_xv_render(port_priv); + glamor_xv_render(port_priv, id); return Success; } |