diff options
Diffstat (limited to 'xserver/glamor')
43 files changed, 3789 insertions, 5693 deletions
diff --git a/xserver/glamor/Makefile.am b/xserver/glamor/Makefile.am index db72cb11c..c631c530b 100644 --- a/xserver/glamor/Makefile.am +++ b/xserver/glamor/Makefile.am @@ -14,7 +14,7 @@ libglamor_la_SOURCES = \ glamor_font.c \ glamor_font.h \ glamor_glx.c \ - glamor_glyphs.c \ + glamor_composite_glyphs.c \ glamor_image.c \ glamor_lines.c \ glamor_segs.c \ @@ -46,10 +46,14 @@ libglamor_la_SOURCES = \ glamor_compositerects.c\ glamor_utils.c\ glamor_utils.h\ - glamor_xv.c \ glamor_sync.c \ glamor.h +if XV +libglamor_la_SOURCES += \ + glamor_xv.c +endif + libglamor_egl_stubs_la_SOURCES = glamor_egl_stubs.c sdk_HEADERS = glamor.h diff --git a/xserver/glamor/Makefile.in b/xserver/glamor/Makefile.in index 53a28429e..c277ec5ee 100644 --- a/xserver/glamor/Makefile.in +++ b/xserver/glamor/Makefile.in @@ -51,6 +51,9 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@XV_TRUE@am__append_1 = \ +@XV_TRUE@ glamor_xv.c + subdir = glamor DIST_COMMON = $(sdk_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp @@ -58,8 +61,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/xorg-tls.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -76,17 +78,33 @@ CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libglamor_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__libglamor_la_SOURCES_DIST = glamor.c glamor_context.h \ + glamor_copy.c glamor_core.c glamor_dash.c glamor_debug.h \ + glamor_font.c glamor_font.h glamor_glx.c \ + glamor_composite_glyphs.c glamor_image.c glamor_lines.c \ + glamor_segs.c glamor_render.c glamor_gradient.c \ + glamor_prepare.c glamor_prepare.h glamor_program.c \ + glamor_program.h glamor_rects.c glamor_spans.c glamor_text.c \ + glamor_transfer.c glamor_transfer.h glamor_transform.c \ + glamor_transform.h glamor_trapezoid.c glamor_triangles.c \ + glamor_addtraps.c glamor_glyphblt.c glamor_points.c \ + glamor_priv.h glamor_pixmap.c glamor_largepixmap.c \ + glamor_picture.c glamor_vbo.c glamor_window.c glamor_fbo.c \ + glamor_compositerects.c glamor_utils.c glamor_utils.h \ + glamor_sync.c glamor.h glamor_xv.c +@XV_TRUE@am__objects_1 = glamor_xv.lo am_libglamor_la_OBJECTS = glamor.lo glamor_copy.lo glamor_core.lo \ - glamor_dash.lo glamor_font.lo glamor_glx.lo glamor_glyphs.lo \ - glamor_image.lo glamor_lines.lo glamor_segs.lo \ - glamor_render.lo glamor_gradient.lo glamor_prepare.lo \ - glamor_program.lo glamor_rects.lo glamor_spans.lo \ - glamor_text.lo glamor_transfer.lo glamor_transform.lo \ - glamor_trapezoid.lo glamor_triangles.lo glamor_addtraps.lo \ - glamor_glyphblt.lo glamor_points.lo glamor_pixmap.lo \ - glamor_largepixmap.lo glamor_picture.lo glamor_vbo.lo \ - glamor_window.lo glamor_fbo.lo glamor_compositerects.lo \ - glamor_utils.lo glamor_xv.lo glamor_sync.lo + glamor_dash.lo glamor_font.lo glamor_glx.lo \ + glamor_composite_glyphs.lo glamor_image.lo glamor_lines.lo \ + glamor_segs.lo glamor_render.lo glamor_gradient.lo \ + glamor_prepare.lo glamor_program.lo glamor_rects.lo \ + glamor_spans.lo glamor_text.lo glamor_transfer.lo \ + glamor_transform.lo glamor_trapezoid.lo glamor_triangles.lo \ + glamor_addtraps.lo glamor_glyphblt.lo glamor_points.lo \ + glamor_pixmap.lo glamor_largepixmap.lo glamor_picture.lo \ + glamor_vbo.lo glamor_window.lo glamor_fbo.lo \ + glamor_compositerects.lo glamor_utils.lo glamor_sync.lo \ + $(am__objects_1) libglamor_la_OBJECTS = $(am_libglamor_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -130,7 +148,7 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libglamor_la_SOURCES) $(libglamor_egl_stubs_la_SOURCES) -DIST_SOURCES = $(libglamor_la_SOURCES) \ +DIST_SOURCES = $(am__libglamor_la_SOURCES_DIST) \ $(libglamor_egl_stubs_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ @@ -260,7 +278,6 @@ GLAMOR_LIBS = @GLAMOR_LIBS@ GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@ GLX_DEFINES = @GLX_DEFINES@ GLX_SYS_LIBS = @GLX_SYS_LIBS@ -GLX_TLS = @GLX_TLS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ @@ -390,8 +407,6 @@ XEPHYR_INCS = @XEPHYR_INCS@ XEPHYR_LIBS = @XEPHYR_LIBS@ XF86CONFIGDIR = @XF86CONFIGDIR@ XF86CONFIGFILE = @XF86CONFIGFILE@ -XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ -XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@ XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@ XKB_COMPILED_DIR = @XKB_COMPILED_DIR@ @@ -518,52 +533,20 @@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libglamor.la libglamor_egl_stubs.la libglamor_la_LIBADD = $(GLAMOR_LIBS) AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) $(GLAMOR_CFLAGS) -libglamor_la_SOURCES = \ - glamor.c \ - glamor_context.h \ - glamor_copy.c \ - glamor_core.c \ - glamor_dash.c \ - glamor_debug.h \ - glamor_font.c \ - glamor_font.h \ - glamor_glx.c \ - glamor_glyphs.c \ - glamor_image.c \ - glamor_lines.c \ - glamor_segs.c \ - glamor_render.c \ - glamor_gradient.c \ - glamor_prepare.c \ - glamor_prepare.h \ - glamor_program.c \ - glamor_program.h \ - glamor_rects.c \ - glamor_spans.c \ - glamor_text.c \ - glamor_transfer.c \ - glamor_transfer.h \ - glamor_transform.c \ - glamor_transform.h \ - glamor_trapezoid.c \ - glamor_triangles.c\ - glamor_addtraps.c\ - glamor_glyphblt.c\ - glamor_points.c\ - glamor_priv.h\ - glamor_pixmap.c\ - glamor_largepixmap.c\ - glamor_picture.c\ - glamor_vbo.c \ - glamor_window.c\ - glamor_fbo.c\ - glamor_compositerects.c\ - glamor_utils.c\ - glamor_utils.h\ - glamor_xv.c \ - glamor_sync.c \ - glamor.h - +libglamor_la_SOURCES = glamor.c glamor_context.h glamor_copy.c \ + glamor_core.c glamor_dash.c glamor_debug.h glamor_font.c \ + glamor_font.h glamor_glx.c glamor_composite_glyphs.c \ + glamor_image.c glamor_lines.c glamor_segs.c glamor_render.c \ + glamor_gradient.c glamor_prepare.c glamor_prepare.h \ + glamor_program.c glamor_program.h glamor_rects.c \ + glamor_spans.c glamor_text.c glamor_transfer.c \ + glamor_transfer.h glamor_transform.c glamor_transform.h \ + glamor_trapezoid.c glamor_triangles.c glamor_addtraps.c \ + glamor_glyphblt.c glamor_points.c glamor_priv.h \ + glamor_pixmap.c glamor_largepixmap.c glamor_picture.c \ + glamor_vbo.c glamor_window.c glamor_fbo.c \ + glamor_compositerects.c glamor_utils.c glamor_utils.h \ + glamor_sync.c glamor.h $(am__append_1) libglamor_egl_stubs_la_SOURCES = glamor_egl_stubs.c sdk_HEADERS = glamor.h all: all-am @@ -624,6 +607,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_addtraps.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_composite_glyphs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_compositerects.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_copy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_core.Plo@am__quote@ @@ -633,7 +617,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_font.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_glx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_glyphblt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_glyphs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_gradient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glamor_largepixmap.Plo@am__quote@ diff --git a/xserver/glamor/glamor.c b/xserver/glamor/glamor.c index 50317b481..8b5eb5493 100644 --- a/xserver/glamor/glamor.c +++ b/xserver/glamor/glamor.c @@ -1,5 +1,5 @@ /* - * Copyright © 2008 Intel Corporation + * Copyright © 2008,2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,7 +23,7 @@ * Authors: * Eric Anholt <eric@anholt.net> * Zhigang Gong <zhigang.gong@linux.intel.com> - * + * Chad Versace <chad.versace@linux.intel.com> */ /** @file glamor.c @@ -34,6 +34,7 @@ #include <stdlib.h> #include "glamor_priv.h" +#include "mipict.h" DevPrivateKeyRec glamor_screen_private_key; DevPrivateKeyRec glamor_pixmap_private_key; @@ -59,26 +60,29 @@ glamor_get_drawable_pixmap(DrawablePtr drawable) return (PixmapPtr) drawable; } +static void +glamor_init_pixmap_private_small(PixmapPtr pixmap, glamor_pixmap_private *pixmap_priv) +{ + pixmap_priv->box.x1 = 0; + pixmap_priv->box.x2 = pixmap->drawable.width; + pixmap_priv->box.y1 = 0; + pixmap_priv->box.y2 = pixmap->drawable.height; + pixmap_priv->block_w = pixmap->drawable.width; + pixmap_priv->block_h = pixmap->drawable.height; + pixmap_priv->block_hcnt = 1; + pixmap_priv->block_wcnt = 1; + pixmap_priv->box_array = &pixmap_priv->box; + pixmap_priv->fbo_array = &pixmap_priv->fbo; +} + _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) { glamor_pixmap_private *pixmap_priv; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - pixmap_priv = dixLookupPrivate(&pixmap->devPrivates, - &glamor_pixmap_private_key); - if (pixmap_priv == NULL) { - pixmap_priv = calloc(sizeof(*pixmap_priv), 1); - glamor_set_pixmap_private(pixmap, pixmap_priv); - pixmap_priv->base.pixmap = pixmap; - pixmap_priv->base.glamor_priv = glamor_priv; - } + pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv->type = type; - pixmap_priv->base.box.x1 = 0; - pixmap_priv->base.box.x2 = pixmap->drawable.width; - pixmap_priv->base.box.y1 = 0; - pixmap_priv->base.box.y2 = pixmap->drawable.height; + glamor_init_pixmap_private_small(pixmap, pixmap_priv); } _X_EXPORT void @@ -93,9 +97,9 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) glamor_priv = glamor_get_screen_private(screen); pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv->base.fbo) { + if (pixmap_priv->fbo) { fbo = glamor_pixmap_detach_fbo(pixmap_priv); - glamor_destroy_fbo(fbo); + glamor_destroy_fbo(glamor_priv, fbo); } format = gl_iformat_for_pixmap(pixmap); @@ -119,10 +123,10 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap) glamor_priv = glamor_get_screen_private(screen_pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - glamor_priv->screen_fbo = pixmap_priv->base.fbo->fb; + glamor_priv->screen_fbo = pixmap_priv->fbo->fb; - pixmap_priv->base.fbo->width = screen_pixmap->drawable.width; - pixmap_priv->base.fbo->height = screen_pixmap->drawable.height; + pixmap_priv->fbo->width = screen_pixmap->drawable.width; + pixmap_priv->fbo->height = screen_pixmap->drawable.height; } uint32_t @@ -133,7 +137,7 @@ glamor_get_pixmap_texture(PixmapPtr pixmap) if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY) return 0; - return pixmap_priv->base.fbo->tex; + return pixmap_priv->fbo->tex; } PixmapPtr @@ -141,7 +145,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { PixmapPtr pixmap; - glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_fbo *fbo = NULL; @@ -152,7 +155,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return NullPixmap; if ((usage == GLAMOR_CREATE_PIXMAP_CPU - || (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 64 && h <= 64) + || (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && + w <= glamor_priv->glyph_max_dim && + h <= glamor_priv->glyph_max_dim) || (w == 0 && h == 0) || !glamor_check_pixmap_fbo_depth(depth)) || (!GLAMOR_TEXTURED_LARGE_PIXMAP && @@ -161,46 +166,28 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); - pixmap_priv = calloc(1, sizeof(*pixmap_priv)); - - if (!pixmap_priv) { - fbDestroyPixmap(pixmap); - return fbCreatePixmap(screen, w, h, depth, usage); - } - glamor_set_pixmap_private(pixmap, pixmap_priv); - - if (usage == GLAMOR_CREATE_PIXMAP_MAP) - type = GLAMOR_MEMORY_MAP; - - pixmap_priv->base.pixmap = pixmap; - pixmap_priv->base.glamor_priv = glamor_priv; + pixmap_priv = glamor_get_pixmap_private(pixmap); format = gl_iformat_for_pixmap(pixmap); pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); + pixmap_priv->type = GLAMOR_TEXTURE_ONLY; + if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) { - pixmap_priv->type = GLAMOR_TEXTURE_ONLY; - pixmap_priv->base.box.x1 = 0; - pixmap_priv->base.box.y1 = 0; - pixmap_priv->base.box.x2 = w; - pixmap_priv->base.box.y2 = h; + glamor_init_pixmap_private_small(pixmap, pixmap_priv); return pixmap; } - else if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE || + else if (usage == GLAMOR_CREATE_NO_LARGE || glamor_check_fbo_size(glamor_priv, w, h)) { - pixmap_priv->type = type; - pixmap_priv->base.box.x1 = 0; - pixmap_priv->base.box.y1 = 0; - pixmap_priv->base.box.x2 = w; - pixmap_priv->base.box.y2 = h; + glamor_init_pixmap_private_small(pixmap, pixmap_priv); fbo = glamor_create_fbo(glamor_priv, w, h, format, 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); - pixmap_priv->type = GLAMOR_TEXTURE_LARGE; + 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, tile_size, tile_size, pixmap_priv); } @@ -219,13 +206,10 @@ void glamor_destroy_textured_pixmap(PixmapPtr pixmap) { if (pixmap->refcnt == 1) { - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv != NULL) { #if GLAMOR_HAS_GBM - glamor_egl_destroy_pixmap_image(pixmap); + glamor_egl_destroy_pixmap_image(pixmap); #endif - glamor_set_pixmap_private(pixmap, NULL); - } + glamor_pixmap_destroy_fbo(pixmap); } } @@ -275,6 +259,68 @@ glamor_set_debug_level(int *debug_level) int glamor_debug_level; +void +glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv, + unsigned count) +{ + unsigned i; + + /* For a single quad, don't bother with an index buffer. */ + if (count == 1) + goto fallback; + + if (glamor_priv->ib_size < count) { + /* Basic GLES2 doesn't have any way to map buffer objects for + * writing, but it's long past time for drivers to have + * MapBufferRange. + */ + if (!glamor_priv->has_map_buffer_range) + goto fallback; + + /* Lazy create the buffer name, and only bind it once since + * none of the glamor code binds it to anything else. + */ + if (!glamor_priv->ib) { + glGenBuffers(1, &glamor_priv->ib); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ib); + } + + /* For now, only support GL_UNSIGNED_SHORTs. */ + if (count > ((1 << 16) - 1) / 4) { + goto fallback; + } else { + uint16_t *data; + size_t size = count * 6 * sizeof(GLushort); + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW); + data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + 0, size, + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT); + for (i = 0; i < count; i++) { + data[i * 6 + 0] = i * 4 + 0; + data[i * 6 + 1] = i * 4 + 1; + data[i * 6 + 2] = i * 4 + 2; + data[i * 6 + 3] = i * 4 + 0; + data[i * 6 + 4] = i * 4 + 2; + data[i * 6 + 5] = i * 4 + 3; + } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + glamor_priv->ib_size = count; + glamor_priv->ib_type = GL_UNSIGNED_SHORT; + } + } + + glDrawElements(GL_TRIANGLES, count * 6, glamor_priv->ib_type, NULL); + return; + +fallback: + for (i = 0; i < count; i++) + glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); +} + + /** * Creates any pixmaps used internally by glamor, since those can't be * allocated at ScreenInit time. @@ -291,16 +337,6 @@ glamor_create_screen_resources(ScreenPtr screen) ret = screen->CreateScreenResources(screen); screen->CreateScreenResources = glamor_create_screen_resources; - if (!glamor_glyphs_init(screen)) { - ErrorF("Failed to initialize glyphs\n"); - ret = FALSE; - } - - if (!glamor_realize_glyph_caches(screen)) { - ErrorF("Failed to initialize glyph cache\n"); - ret = FALSE; - } - return ret; } @@ -333,17 +369,68 @@ glamor_check_instruction_count(int gl_version) return TRUE; } +static void GLAPIENTRY +glamor_debug_output_callback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *message, + const void *userParam) +{ + ScreenPtr screen = (void *)userParam; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + if (glamor_priv->suppress_gl_out_of_memory_logging && + source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) { + return; + } + + LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n", + screen->myNum, length, message); +} + +/** + * Configures GL_ARB_debug_output to give us immediate callbacks when + * GL errors occur, so that we can log them. + */ +static void +glamor_setup_debug_output(ScreenPtr screen) +{ + if (!epoxy_has_gl_extension("GL_ARB_debug_output")) + return; + + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + /* Disable debugging messages other than GL API errors */ + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, + GL_FALSE); + glDebugMessageControl(GL_DEBUG_SOURCE_API, + GL_DEBUG_TYPE_ERROR, + GL_DONT_CARE, + 0, NULL, GL_TRUE); + glDebugMessageCallback(glamor_debug_output_callback, + screen); + + /* If KHR_debug is present, all debug output is disabled by + * default on non-debug contexts. + */ + if (epoxy_has_gl_extension("GL_KHR_debug")) + glEnable(GL_DEBUG_OUTPUT); +} + /** Set up glamor for an already-configured GL context. */ Bool glamor_init(ScreenPtr screen, unsigned int flags) { glamor_screen_private *glamor_priv; int gl_version; + int glsl_major, glsl_minor; int max_viewport_size[2]; + const char *shading_version_string; + int shading_version_offset; -#ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); -#endif + if (flags & ~GLAMOR_VALID_FLAGS) { ErrorF("glamor_init: Invalid flags %x\n", flags); return FALSE; @@ -363,7 +450,8 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_set_screen_private(screen, glamor_priv); - if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) { + if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, + sizeof(struct glamor_pixmap_private))) { LogMessage(X_WARNING, "glamor%d: Failed to allocate pixmap private\n", screen->myNum); @@ -399,14 +487,40 @@ glamor_init(ScreenPtr screen, unsigned int flags) gl_version = epoxy_gl_version(); - /* Would be nice to have a cleaner test for GLSL 1.30 support, - * but for now this should suffice - */ - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && gl_version >= 30) - glamor_priv->glsl_version = 130; - else - glamor_priv->glsl_version = 120; + shading_version_string = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); + + if (!shading_version_string) { + LogMessage(X_WARNING, + "glamor%d: Failed to get GLSL version\n", + screen->myNum); + goto fail; + } + shading_version_offset = 0; + if (strncmp("OpenGL ES GLSL ES ", shading_version_string, 18) == 0) + shading_version_offset = 18; + + if (sscanf(shading_version_string + shading_version_offset, + "%i.%i", + &glsl_major, + &glsl_minor) != 2) { + LogMessage(X_WARNING, + "glamor%d: Failed to parse GLSL version string %s\n", + screen->myNum, shading_version_string); + goto fail; + } + glamor_priv->glsl_version = glsl_major * 100 + glsl_minor; + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + /* 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 + * ES 3.0, but our glamor_program.c constructions use a lot of + * compatibility features (to reduce the diff between 1.20 and + * 1.30 programs). + */ + glamor_priv->glsl_version = 120; + } /* We'd like to require GL_ARB_map_buffer_range or * GL_OES_map_buffer_range, since it offers more information to @@ -451,7 +565,8 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->has_fbo_blit = epoxy_has_gl_extension("GL_EXT_framebuffer_blit"); glamor_priv->has_map_buffer_range = - epoxy_has_gl_extension("GL_ARB_map_buffer_range"); + epoxy_has_gl_extension("GL_ARB_map_buffer_range") || + epoxy_has_gl_extension("GL_EXT_map_buffer_range"); glamor_priv->has_buffer_storage = epoxy_has_gl_extension("GL_ARB_buffer_storage"); glamor_priv->has_nv_texture_barrier = @@ -464,6 +579,27 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP || epoxy_gl_version() >= 30 || epoxy_has_gl_extension("GL_NV_pack_subimage"); + glamor_priv->has_vertex_array_object = + epoxy_has_gl_extension("GL_ARB_vertex_array_object"); + glamor_priv->has_dual_blend = + epoxy_has_gl_extension("GL_ARB_blend_func_extended"); + + /* assume a core profile if we are GL 3.1 and don't have ARB_compatibility */ + glamor_priv->is_core_profile = + gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility"); + + glamor_setup_debug_output(screen); + + glamor_priv->use_quads = (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) && + !glamor_priv->is_core_profile; + + /* Driver-specific hack: Avoid using GL_QUADS on VC4, where + * they'll be emulated more expensively than we can with our + * cached IB. + */ + if (strstr((char *)glGetString(GL_VENDOR), "Broadcom") && + strstr((char *)glGetString(GL_RENDERER), "VC4")) + glamor_priv->use_quads = FALSE; glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size); @@ -474,6 +610,10 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->max_fbo_size = MAX_FBO_SIZE; #endif + glamor_priv->one_channel_format = GL_ALPHA; + if (epoxy_has_gl_extension("GL_ARB_texture_rg") && epoxy_has_gl_extension("GL_ARB_texture_swizzle")) + glamor_priv->one_channel_format = GL_RED; + glamor_set_debug_level(&glamor_debug_level); glamor_priv->saved_procs.create_screen_resources = @@ -483,74 +623,61 @@ glamor_init(ScreenPtr screen, unsigned int flags) if (!glamor_font_init(screen)) goto fail; - if (flags & GLAMOR_USE_SCREEN) { + glamor_priv->saved_procs.block_handler = screen->BlockHandler; + screen->BlockHandler = _glamor_block_handler; - glamor_priv->saved_procs.block_handler = screen->BlockHandler; - screen->BlockHandler = _glamor_block_handler; + if (!glamor_composite_glyphs_init(screen)) { + ErrorF("Failed to initialize composite masks\n"); + goto fail; + } - glamor_priv->saved_procs.create_gc = screen->CreateGC; - screen->CreateGC = glamor_create_gc; + glamor_priv->saved_procs.create_gc = screen->CreateGC; + screen->CreateGC = glamor_create_gc; - glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap; - screen->CreatePixmap = glamor_create_pixmap; + glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap; + screen->CreatePixmap = glamor_create_pixmap; - glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap; - screen->DestroyPixmap = glamor_destroy_pixmap; + glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap; + screen->DestroyPixmap = glamor_destroy_pixmap; - glamor_priv->saved_procs.get_spans = screen->GetSpans; - screen->GetSpans = glamor_get_spans; + glamor_priv->saved_procs.get_spans = screen->GetSpans; + screen->GetSpans = glamor_get_spans; - glamor_priv->saved_procs.get_image = screen->GetImage; - screen->GetImage = glamor_get_image; + glamor_priv->saved_procs.get_image = screen->GetImage; + screen->GetImage = glamor_get_image; - glamor_priv->saved_procs.change_window_attributes = - screen->ChangeWindowAttributes; - screen->ChangeWindowAttributes = glamor_change_window_attributes; + glamor_priv->saved_procs.change_window_attributes = + screen->ChangeWindowAttributes; + screen->ChangeWindowAttributes = glamor_change_window_attributes; - glamor_priv->saved_procs.copy_window = screen->CopyWindow; - screen->CopyWindow = glamor_copy_window; + glamor_priv->saved_procs.copy_window = screen->CopyWindow; + screen->CopyWindow = glamor_copy_window; - glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion; - screen->BitmapToRegion = glamor_bitmap_to_region; - } -#ifdef RENDER - if (flags & GLAMOR_USE_PICTURE_SCREEN) { - glamor_priv->saved_procs.composite = ps->Composite; - ps->Composite = glamor_composite; + glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion; + screen->BitmapToRegion = glamor_bitmap_to_region; - glamor_priv->saved_procs.trapezoids = ps->Trapezoids; - ps->Trapezoids = glamor_trapezoids; + glamor_priv->saved_procs.composite = ps->Composite; + ps->Composite = glamor_composite; - glamor_priv->saved_procs.triangles = ps->Triangles; - ps->Triangles = glamor_triangles; + glamor_priv->saved_procs.trapezoids = ps->Trapezoids; + ps->Trapezoids = glamor_trapezoids; - glamor_priv->saved_procs.addtraps = ps->AddTraps; - ps->AddTraps = glamor_add_traps; + glamor_priv->saved_procs.triangles = ps->Triangles; + ps->Triangles = glamor_triangles; - } + glamor_priv->saved_procs.addtraps = ps->AddTraps; + ps->AddTraps = glamor_add_traps; glamor_priv->saved_procs.composite_rects = ps->CompositeRects; ps->CompositeRects = glamor_composite_rectangles; glamor_priv->saved_procs.glyphs = ps->Glyphs; - ps->Glyphs = glamor_glyphs; - - glamor_priv->saved_procs.unrealize_glyph = ps->UnrealizeGlyph; - ps->UnrealizeGlyph = glamor_glyph_unrealize; - - glamor_priv->saved_procs.create_picture = ps->CreatePicture; - ps->CreatePicture = glamor_create_picture; - - glamor_priv->saved_procs.destroy_picture = ps->DestroyPicture; - ps->DestroyPicture = glamor_destroy_picture; - glamor_init_composite_shaders(screen); -#endif - glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap; - screen->SetWindowPixmap = glamor_set_window_pixmap; + ps->Glyphs = glamor_composite_glyphs; glamor_init_vbo(screen); glamor_init_pixmap_fbo(screen); glamor_init_finish_access_shaders(screen); + #ifdef GLAMOR_GRADIENT_SHADER glamor_init_gradient_shader(screen); #endif @@ -573,86 +700,46 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_screen_private *glamor_priv; glamor_priv = glamor_get_screen_private(screen); -#ifdef RENDER - glamor_fini_composite_shaders(screen); -#endif glamor_fini_vbo(screen); glamor_fini_pixmap_fbo(screen); - glamor_fini_finish_access_shaders(screen); -#ifdef GLAMOR_GRADIENT_SHADER - glamor_fini_gradient_shader(screen); -#endif glamor_pixmap_fini(screen); free(glamor_priv); glamor_set_screen_private(screen, NULL); } -_X_EXPORT void -glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv) -{ - glamor_pixmap_private *old_priv; - - old_priv = dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key); - - if (priv) { - assert(old_priv == NULL); - } - else { - if (old_priv == NULL) - return; - - glamor_pixmap_destroy_fbo(old_priv); - free(old_priv); - } - - dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key, priv); -} - Bool glamor_close_screen(ScreenPtr screen) { glamor_screen_private *glamor_priv; PixmapPtr screen_pixmap; - int flags; - -#ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); -#endif + glamor_priv = glamor_get_screen_private(screen); - flags = glamor_priv->flags; glamor_sync_close(screen); - glamor_glyphs_fini(screen); + glamor_composite_glyphs_fini(screen); screen->CloseScreen = glamor_priv->saved_procs.close_screen; screen->CreateScreenResources = glamor_priv->saved_procs.create_screen_resources; - if (flags & GLAMOR_USE_SCREEN) { - - screen->CreateGC = glamor_priv->saved_procs.create_gc; - screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; - screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; - screen->GetSpans = glamor_priv->saved_procs.get_spans; - screen->ChangeWindowAttributes = - glamor_priv->saved_procs.change_window_attributes; - screen->CopyWindow = glamor_priv->saved_procs.copy_window; - screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region; - screen->BlockHandler = glamor_priv->saved_procs.block_handler; - } -#ifdef RENDER - if (ps && (flags & GLAMOR_USE_PICTURE_SCREEN)) { - ps->Composite = glamor_priv->saved_procs.composite; - ps->Trapezoids = glamor_priv->saved_procs.trapezoids; - ps->Triangles = glamor_priv->saved_procs.triangles; - ps->CreatePicture = glamor_priv->saved_procs.create_picture; - } + screen->CreateGC = glamor_priv->saved_procs.create_gc; + screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; + screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; + screen->GetSpans = glamor_priv->saved_procs.get_spans; + screen->ChangeWindowAttributes = + glamor_priv->saved_procs.change_window_attributes; + screen->CopyWindow = glamor_priv->saved_procs.copy_window; + screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region; + screen->BlockHandler = glamor_priv->saved_procs.block_handler; + + ps->Composite = glamor_priv->saved_procs.composite; + ps->Trapezoids = glamor_priv->saved_procs.trapezoids; + ps->Triangles = glamor_priv->saved_procs.triangles; ps->CompositeRects = glamor_priv->saved_procs.composite_rects; ps->Glyphs = glamor_priv->saved_procs.glyphs; - ps->UnrealizeGlyph = glamor_priv->saved_procs.unrealize_glyph; - screen->SetWindowPixmap = glamor_priv->saved_procs.set_window_pixmap; -#endif + screen_pixmap = screen->GetScreenPixmap(screen); - glamor_set_pixmap_private(screen_pixmap, NULL); + glamor_pixmap_destroy_fbo(screen_pixmap); glamor_release_screen_priv(screen); @@ -685,12 +772,11 @@ _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, CARD16 *stride, CARD32 *size) { - glamor_pixmap_private *pixmap_priv; + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL || !glamor_priv->dri3_enabled) + if (!glamor_priv->dri3_enabled) return -1; switch (pixmap_priv->type) { case GLAMOR_TEXTURE_DRM: @@ -699,7 +785,7 @@ glamor_fd_from_pixmap(ScreenPtr screen, return -1; return glamor_egl_dri3_fd_name_from_tex(screen, pixmap, - pixmap_priv->base.fbo->tex, + pixmap_priv->fbo->tex, FALSE, stride, size); default: break; @@ -710,13 +796,10 @@ glamor_fd_from_pixmap(ScreenPtr screen, int glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size) { - glamor_pixmap_private *pixmap_priv; + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL) - return -1; switch (pixmap_priv->type) { case GLAMOR_TEXTURE_DRM: case GLAMOR_TEXTURE_ONLY: @@ -724,7 +807,7 @@ glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size) return -1; return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen, pixmap, - pixmap_priv->base.fbo->tex, + pixmap_priv->fbo->tex, TRUE, stride, size); default: break; diff --git a/xserver/glamor/glamor.h b/xserver/glamor/glamor.h index 206158c02..0aa6d5604 100644 --- a/xserver/glamor/glamor.h +++ b/xserver/glamor/glamor.h @@ -52,50 +52,34 @@ struct glamor_context; * @TEXTURE_ONLY: pixmap is in an internal texture. */ typedef enum glamor_pixmap_type { - GLAMOR_MEMORY, - GLAMOR_MEMORY_MAP, + GLAMOR_MEMORY = 0, /* Newly calloc()ed pixmaps are memory. */ GLAMOR_TEXTURE_DRM, - GLAMOR_SEPARATE_TEXTURE, GLAMOR_DRM_ONLY, GLAMOR_TEXTURE_ONLY, - GLAMOR_TEXTURE_LARGE, - GLAMOR_TEXTURE_PACK } glamor_pixmap_type_t; #define GLAMOR_EGL_EXTERNAL_BUFFER 3 -#define GLAMOR_INVERTED_Y_AXIS 1 /* compat stub */ -#define GLAMOR_USE_SCREEN (1 << 1) -#define GLAMOR_USE_PICTURE_SCREEN (1 << 2) -#define GLAMOR_USE_EGL_SCREEN (1 << 3) -#define GLAMOR_NO_DRI3 (1 << 4) -#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS \ - | GLAMOR_USE_SCREEN \ - | GLAMOR_USE_PICTURE_SCREEN \ - | GLAMOR_USE_EGL_SCREEN \ +#define GLAMOR_USE_EGL_SCREEN (1 << 0) +#define GLAMOR_NO_DRI3 (1 << 1) +#define GLAMOR_VALID_FLAGS (GLAMOR_USE_EGL_SCREEN \ | GLAMOR_NO_DRI3) +/* until we need geometry shaders GL3.1 should suffice. */ +#define GLAMOR_GL_CORE_VER_MAJOR 3 +#define GLAMOR_GL_CORE_VER_MINOR 1 + /* @glamor_init: Initialize glamor internal data structure. * * @screen: Current screen pointer. * @flags: Please refer the flags description above. * - * @GLAMOR_USE_SCREEN: - * If running in an pre-existing X environment, and the - * gl context is GLX, then you should set this bit and - * let the glamor to handle all the screen related - * functions such as GC ops and CreatePixmap/DestroyPixmap. - * - * @GLAMOR_USE_PICTURE_SCREEN: - * If don't use any other underlying DDX driver to handle - * the picture related rendering functions, please set this - * bit on. Otherwise, clear this bit. And then it is the DDX - * driver's responsibility to determine how/when to jump to - * glamor's picture compositing path. - * * @GLAMOR_USE_EGL_SCREEN: * If you are using EGL layer, then please set this bit * on, otherwise, clear it. * + * @GLAMOR_NO_DRI3 + * Disable the built-in DRI3 support + * * This function initializes necessary internal data structure * for glamor. And before calling into this function, the OpenGL * environment should be ready. Should be called before any real @@ -125,8 +109,6 @@ extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap, extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap); -extern _X_EXPORT Bool glamor_glyphs_init(ScreenPtr pScreen); - extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex); @@ -142,7 +124,6 @@ extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap); #define GLAMOR_CREATE_PIXMAP_CPU 0x100 #define GLAMOR_CREATE_PIXMAP_FIXUP 0x101 #define GLAMOR_CREATE_FBO_NO_FBO 0x103 -#define GLAMOR_CREATE_PIXMAP_MAP 0x104 #define GLAMOR_CREATE_NO_LARGE 0x105 #define GLAMOR_CREATE_PIXMAP_NO_TEXTURE 0x106 @@ -165,7 +146,8 @@ extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen); extern _X_EXPORT unsigned int glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, - int h); + int h, + Bool linear); extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr, unsigned int, Bool, CARD16 *, CARD32 *); @@ -220,6 +202,21 @@ extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen, extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size); +/* @glamor_gbm_bo_from_pixmap: Get a GBM bo from a pixmap. + * + * @screen: Current screen pointer. + * @pixmap: The pixmap from which we want the fd. + * @stride, @size: Pointers to fill the stride and size of the + * buffer associated to the fd. + * + * the pixmap and the buffer represented by the gbm_bo will share the same + * content. + * + * Returns the gbm_bo on success, NULL on error. + * */ +extern _X_EXPORT void *glamor_gbm_bo_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap); + /* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd. * * @screen: Current screen pointer. @@ -240,6 +237,25 @@ extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen, CARD8 depth, CARD8 bpp); +/* @glamor_back_pixmap_from_fd: Backs an existing pixmap with a dma-buf fd. + * + * @pixmap: Pixmap to change backing for + * @fd: The dma-buf fd to import. + * @width: The width of the buffer. + * @height: The height of the buffer. + * @stride: The stride of the buffer. + * @depth: The depth of the buffer. + * @bpp: The number of bpp of the buffer. + * + * Returns TRUE if successful, FALSE on failure. + * */ +extern _X_EXPORT Bool glamor_back_pixmap_from_fd(PixmapPtr pixmap, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, + CARD8 depth, + CARD8 bpp); #ifdef GLAMOR_FOR_XORG #define GLAMOR_EGL_MODULE_NAME "glamoregl" @@ -326,146 +342,6 @@ extern _X_EXPORT void glamor_destroy_gc(GCPtr gc); extern Bool _X_EXPORT glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); extern void _X_EXPORT glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region); -/* Glamor rendering/drawing functions with XXX_nf. - * nf means no fallback within glamor internal if possible. If glamor - * fail to accelerate the operation, glamor will return a false, and the - * caller need to implement fallback method. Return a true means the - * rendering request get done successfully. */ -extern _X_EXPORT Bool glamor_fill_spans_nf(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, - int *widths, int sorted); - -extern _X_EXPORT Bool glamor_poly_fill_rect_nf(DrawablePtr drawable, - GCPtr gc, - int nrect, xRectangle *prect); - -extern _X_EXPORT Bool glamor_put_image_nf(DrawablePtr drawable, - GCPtr gc, int depth, int x, int y, - int w, int h, int left_pad, - int image_format, char *bits); - -extern _X_EXPORT Bool glamor_copy_n_to_n_nf(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, - void *closure); - -extern _X_EXPORT Bool glamor_copy_nf(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, - void *closure); - -extern _X_EXPORT Bool glamor_composite_nf(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height); - -extern _X_EXPORT Bool glamor_trapezoids_nf(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid *traps); - -extern _X_EXPORT Bool glamor_glyphs_nf(CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, int nlist, - GlyphListPtr list, GlyphPtr *glyphs); - -extern _X_EXPORT Bool glamor_triangles_nf(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int ntris, xTriangle *tris); - -extern _X_EXPORT void glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph); - -extern _X_EXPORT Bool glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, - char *src, DDXPointPtr points, - int *widths, int n, int sorted); - -extern _X_EXPORT Bool glamor_get_spans_nf(DrawablePtr drawable, int wmax, - DDXPointPtr points, int *widths, - int count, char *dst); - -extern _X_EXPORT Bool glamor_composite_rects_nf(CARD8 op, - PicturePtr pDst, - xRenderColor *color, - int nRect, xRectangle *rects); - -extern _X_EXPORT Bool glamor_get_image_nf(DrawablePtr pDrawable, int x, int y, - int w, int h, unsigned int format, - unsigned long planeMask, char *d); - -extern _X_EXPORT Bool glamor_add_traps_nf(PicturePtr pPicture, - INT16 x_off, - INT16 y_off, int ntrap, - xTrap *traps); - -extern _X_EXPORT Bool glamor_copy_plane_nf(DrawablePtr pSrc, DrawablePtr pDst, - GCPtr pGC, int srcx, int srcy, int w, - int h, int dstx, int dsty, - unsigned long bitPlane, - RegionPtr *pRegion); - -extern _X_EXPORT Bool glamor_image_glyph_blt_nf(DrawablePtr pDrawable, - GCPtr pGC, int x, int y, - unsigned int nglyph, - CharInfoPtr *ppci, - void *pglyphBase); - -extern _X_EXPORT Bool glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, - unsigned int nglyph, - CharInfoPtr *ppci, - void *pglyphBase); - -extern _X_EXPORT Bool glamor_push_pixels_nf(GCPtr pGC, PixmapPtr pBitmap, - DrawablePtr pDrawable, int w, int h, - int x, int y); - -extern _X_EXPORT Bool glamor_poly_point_nf(DrawablePtr pDrawable, GCPtr pGC, - int mode, int npt, DDXPointPtr ppt); - -extern _X_EXPORT Bool glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC, - int nseg, xSegment *pSeg); - -extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, - int mode, int n, DDXPointPtr points); - -extern _X_EXPORT Bool glamor_poly_text8_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, char *chars, int *final_pos); - -extern _X_EXPORT Bool glamor_poly_text16_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, unsigned short *chars, int *final_pos); - -extern _X_EXPORT Bool glamor_image_text8_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, char *chars); - -extern _X_EXPORT Bool glamor_image_text16_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, unsigned short *chars); - #define HAS_GLAMOR_TEXT 1 #ifdef GLAMOR_FOR_XORG diff --git a/xserver/glamor/glamor_addtraps.c b/xserver/glamor/glamor_addtraps.c index fdc0f4232..7ad9f3000 100644 --- a/xserver/glamor/glamor_addtraps.c +++ b/xserver/glamor/glamor_addtraps.c @@ -28,34 +28,13 @@ #include "glamor_priv.h" -static Bool -_glamor_add_traps(PicturePtr pPicture, - INT16 x_off, - INT16 y_off, int ntrap, xTrap *traps, Bool fallback) +void +glamor_add_traps(PicturePtr pPicture, + INT16 x_off, + INT16 y_off, int ntrap, xTrap *traps) { - if (!fallback - && (!pPicture->pDrawable - || glamor_ddx_fallback_check_pixmap(pPicture->pDrawable))) - return FALSE; - if (glamor_prepare_access_picture(pPicture, GLAMOR_ACCESS_RW)) { fbAddTraps(pPicture, x_off, y_off, ntrap, traps); } glamor_finish_access_picture(pPicture); - - return TRUE; -} - -void -glamor_add_traps(PicturePtr pPicture, - INT16 x_off, INT16 y_off, int ntrap, xTrap *traps) -{ - _glamor_add_traps(pPicture, x_off, y_off, ntrap, traps, TRUE); -} - -Bool -glamor_add_traps_nf(PicturePtr pPicture, - INT16 x_off, INT16 y_off, int ntrap, xTrap *traps) -{ - return _glamor_add_traps(pPicture, x_off, y_off, ntrap, traps, FALSE); } diff --git a/xserver/glamor/glamor_composite_glyphs.c b/xserver/glamor/glamor_composite_glyphs.c new file mode 100644 index 000000000..f51ff6dad --- /dev/null +++ b/xserver/glamor/glamor_composite_glyphs.c @@ -0,0 +1,573 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include <stdlib.h> +#include "Xprintf.h" + +#include "glamor_priv.h" +#include "glamor_transform.h" +#include "glamor_transfer.h" + +#include <mipict.h> + +#define DEFAULT_ATLAS_DIM 1024 + +static DevPrivateKeyRec glamor_glyph_private_key; + +struct glamor_glyph_private { + int16_t x; + int16_t y; + uint32_t serial; +}; + +struct glamor_glyph_atlas { + PixmapPtr atlas; + PictFormatPtr format; + int x, y; + int row_height; + int nglyph; + uint32_t serial; +}; + +static inline struct glamor_glyph_private *glamor_get_glyph_private(PixmapPtr pixmap) { + return dixLookupPrivate(&pixmap->devPrivates, &glamor_glyph_private_key); +} + +static inline void +glamor_copy_glyph(PixmapPtr glyph_pixmap, + DrawablePtr atlas_draw, + int16_t x, + int16_t y) +{ + DrawablePtr glyph_draw = &glyph_pixmap->drawable; + BoxRec box = { + .x1 = 0, + .y1 = 0, + .x2 = glyph_draw->width, + .y2 = glyph_draw->height, + }; + PixmapPtr upload_pixmap = glyph_pixmap; + + if (glyph_pixmap->drawable.bitsPerPixel != atlas_draw->bitsPerPixel) { + + /* If we're dealing with 1-bit glyphs, we copy them to a + * temporary 8-bit pixmap and upload them from there, since + * that's what GL can handle. + */ + ScreenPtr screen = atlas_draw->pScreen; + GCPtr scratch_gc; + ChangeGCVal changes[2]; + + upload_pixmap = glamor_create_pixmap(screen, + glyph_draw->width, + glyph_draw->height, + atlas_draw->depth, + GLAMOR_CREATE_PIXMAP_CPU); + if (!upload_pixmap) + return; + + scratch_gc = GetScratchGC(upload_pixmap->drawable.depth, screen); + if (!scratch_gc) { + glamor_destroy_pixmap(upload_pixmap); + return; + } + changes[0].val = 0xff; + changes[1].val = 0x00; + if (ChangeGC(NullClient, scratch_gc, + GCForeground|GCBackground, changes) != Success) { + glamor_destroy_pixmap(upload_pixmap); + FreeScratchGC(scratch_gc); + return; + } + ValidateGC(&upload_pixmap->drawable, scratch_gc); + + (*scratch_gc->ops->CopyPlane)(glyph_draw, + &upload_pixmap->drawable, + scratch_gc, + 0, 0, + glyph_draw->width, + glyph_draw->height, + 0, 0, 0x1); + } + glamor_upload_boxes((PixmapPtr) atlas_draw, + &box, 1, + 0, 0, + x, y, + upload_pixmap->devPrivate.ptr, + upload_pixmap->devKind); + + if (upload_pixmap != glyph_pixmap) + glamor_destroy_pixmap(upload_pixmap); +} + +static Bool +glamor_glyph_atlas_init(ScreenPtr screen, struct glamor_glyph_atlas *atlas) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PictFormatPtr format = atlas->format; + + atlas->atlas = glamor_create_pixmap(screen, glamor_priv->glyph_atlas_dim, + glamor_priv->glyph_atlas_dim, format->depth, + GLAMOR_CREATE_FBO_NO_FBO); + if (!glamor_pixmap_has_fbo(atlas->atlas)) { + glamor_destroy_pixmap(atlas->atlas); + atlas->atlas = NULL; + } + atlas->x = 0; + atlas->y = 0; + atlas->row_height = 0; + atlas->serial++; + atlas->nglyph = 0; + return TRUE; +} + +static Bool +glamor_glyph_can_add(struct glamor_glyph_atlas *atlas, int dim, DrawablePtr glyph_draw) +{ + /* Step down */ + if (atlas->x + glyph_draw->width > dim) { + atlas->x = 0; + atlas->y += atlas->row_height; + atlas->row_height = 0; + } + + /* Check for overfull */ + if (atlas->y + glyph_draw->height > dim) + return FALSE; + + return TRUE; +} + +static Bool +glamor_glyph_add(struct glamor_glyph_atlas *atlas, DrawablePtr glyph_draw) +{ + PixmapPtr glyph_pixmap = (PixmapPtr) glyph_draw; + struct glamor_glyph_private *glyph_priv = glamor_get_glyph_private(glyph_pixmap); + + glamor_copy_glyph(glyph_pixmap, &atlas->atlas->drawable, atlas->x, atlas->y); + + glyph_priv->x = atlas->x; + glyph_priv->y = atlas->y; + glyph_priv->serial = atlas->serial; + + atlas->x += glyph_draw->width; + if (atlas->row_height < glyph_draw->height) + atlas->row_height = glyph_draw->height; + + atlas->nglyph++; + + return TRUE; +} + +static const glamor_facet glamor_facet_composite_glyphs_130 = { + .name = "composite_glyphs", + .version = 130, + .vs_vars = ("attribute vec4 primitive;\n" + "attribute vec2 source;\n" + "varying vec2 glyph_pos;\n"), + .vs_exec = (" vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n" + GLAMOR_POS(gl_Position, (primitive.xy + pos)) + " glyph_pos = (source + pos) * ATLAS_DIM_INV;\n"), + .fs_vars = ("varying vec2 glyph_pos;\n" + "out vec4 color0;\n" + "out vec4 color1;\n"), + .fs_exec = (" vec4 mask = texture2D(atlas, glyph_pos);\n"), + .source_name = "source", + .locations = glamor_program_location_atlas, +}; + +static const glamor_facet glamor_facet_composite_glyphs_120 = { + .name = "composite_glyphs", + .vs_vars = ("attribute vec2 primitive;\n" + "attribute vec2 source;\n" + "varying vec2 glyph_pos;\n"), + .vs_exec = (GLAMOR_POS(gl_Position, primitive) + " glyph_pos = source.xy * ATLAS_DIM_INV;\n"), + .fs_vars = ("varying vec2 glyph_pos;\n"), + .fs_exec = (" vec4 mask = texture2D(atlas, glyph_pos);\n"), + .source_name = "source", + .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) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + return asprintf(&glamor_priv->glyph_defines, "#define ATLAS_DIM_INV %20.18f\n", 1.0/glamor_priv->glyph_atlas_dim) > 0; +} + +static void +glamor_glyphs_fini_facet(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + free(glamor_priv->glyph_defines); +} + +static void +glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst, + glamor_program *prog, + struct glamor_glyph_atlas *atlas, int nglyph) +{ + DrawablePtr drawable = dst->pDrawable; + glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); + PixmapPtr atlas_pixmap = atlas->atlas; + glamor_pixmap_private *atlas_priv = glamor_get_pixmap_private(atlas_pixmap); + glamor_pixmap_fbo *atlas_fbo = glamor_pixmap_fbo_at(atlas_priv, 0); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + int box_index; + int off_x, off_y; + + glamor_put_vbo_space(drawable->pScreen); + + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, atlas_fbo->tex); + + for (;;) { + if (!glamor_use_program_render(prog, op, src, dst)) + break; + + glUniform1i(prog->atlas_uniform, 1); + + glamor_pixmap_loop(pixmap_priv, box_index) { + BoxPtr box = RegionRects(dst->pCompositeClip); + int nbox = RegionNumRects(dst->pCompositeClip); + + glamor_set_destination_drawable(drawable, box_index, TRUE, FALSE, + prog->matrix_uniform, + &off_x, &off_y); + + /* Run over the clip list, drawing the glyphs + * in each box + */ + + while (nbox--) { + glScissor(box->x1 + off_x, + box->y1 + off_y, + box->x2 - box->x1, + box->y2 - box->y1); + box++; + + if (glamor_glyph_use_130(glamor_priv)) + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph); + else + glamor_glDrawArrays_GL_QUADS(glamor_priv, nglyph); + } + } + if (prog->alpha != glamor_program_alpha_ca_first) + break; + prog++; + } + + glDisable(GL_SCISSOR_TEST); + + if (glamor_glyph_use_130(glamor_priv)) { + glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); + } + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + glDisable(GL_BLEND); +} + +static GLshort * +glamor_glyph_start(ScreenPtr screen, int count) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + GLshort *v; + char *vbo_offset; + + /* Set up the vertex buffers for the font and destination */ + + if (glamor_glyph_use_130(glamor_priv)) { + v = glamor_get_vbo_space(screen, count * (6 * sizeof (GLshort)), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE, + 6 * sizeof (GLshort), vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1); + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE, + 6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort)); + } else { + v = glamor_get_vbo_space(screen, count * (16 * sizeof (GLshort)), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, + 4 * sizeof (GLshort), vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE, + 4 * sizeof (GLshort), vbo_offset + 2 * sizeof (GLshort)); + } + return v; +} + +static inline struct glamor_glyph_atlas * +glamor_atlas_for_glyph(glamor_screen_private *glamor_priv, DrawablePtr drawable) +{ + if (drawable->depth == 32) + return glamor_priv->glyph_atlas_argb; + else + return glamor_priv->glyph_atlas_a; +} + +void +glamor_composite_glyphs(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr glyph_format, + INT16 x_src, + INT16 y_src, int nlist, GlyphListPtr list, + GlyphPtr *glyphs) +{ + int glyphs_queued; + GLshort *v = NULL; + DrawablePtr drawable = dst->pDrawable; + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_program *prog = NULL; + glamor_program_render *glyphs_program = &glamor_priv->glyphs_program; + struct glamor_glyph_atlas *glyph_atlas = NULL; + int x = 0, y = 0; + int n; + int glyph_atlas_dim = glamor_priv->glyph_atlas_dim; + int glyph_max_dim = glamor_priv->glyph_max_dim; + int nglyph = 0; + int screen_num = screen->myNum; + + for (n = 0; n < nlist; n++) + nglyph += list[n].len; + + glamor_make_current(glamor_priv); + + glyphs_queued = 0; + + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) { + GlyphPtr glyph = *glyphs++; + + /* Glyph not empty? + */ + if (glyph->info.width && glyph->info.height) { + PicturePtr glyph_pict = GlyphPicture(glyph)[screen_num]; + DrawablePtr glyph_draw = glyph_pict->pDrawable; + + /* Need to draw with slow path? + */ + if (_X_UNLIKELY(glyph_draw->width > glyph_max_dim || + glyph_draw->height > glyph_max_dim || + !glamor_pixmap_is_memory((PixmapPtr)glyph_draw))) + { + if (glyphs_queued) { + glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued); + glyphs_queued = 0; + } + bail_one: + glamor_composite(op, src, glyph_pict, dst, + x_src + (x - glyph->info.x), (y - glyph->info.y), + 0, 0, + x - glyph->info.x, y - glyph->info.y, + glyph_draw->width, glyph_draw->height); + } else { + struct glamor_glyph_private *glyph_priv = glamor_get_glyph_private((PixmapPtr)(glyph_draw)); + struct glamor_glyph_atlas *next_atlas = glamor_atlas_for_glyph(glamor_priv, glyph_draw); + + /* Switching source glyph format? + */ + if (_X_UNLIKELY(next_atlas != glyph_atlas)) { + if (glyphs_queued) { + glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued); + glyphs_queued = 0; + } + glyph_atlas = next_atlas; + } + + /* Glyph not cached in current atlas? + */ + if (_X_UNLIKELY(glyph_priv->serial != glyph_atlas->serial)) { + if (!glamor_glyph_can_add(glyph_atlas, glyph_atlas_dim, glyph_draw)) { + if (glyphs_queued) { + glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued); + glyphs_queued = 0; + } + if (glyph_atlas->atlas) { + (*screen->DestroyPixmap)(glyph_atlas->atlas); + glyph_atlas->atlas = NULL; + } + } + if (!glyph_atlas->atlas) { + glamor_glyph_atlas_init(screen, glyph_atlas); + if (!glyph_atlas->atlas) + goto bail_one; + } + glamor_glyph_add(glyph_atlas, glyph_draw); + } + + /* First glyph in the current atlas? + */ + if (_X_UNLIKELY(glyphs_queued == 0)) { + if (glamor_glyph_use_130(glamor_priv)) + prog = glamor_setup_program_render(op, src, glyph_pict, dst, + glyphs_program, + &glamor_facet_composite_glyphs_130, + glamor_priv->glyph_defines); + else + prog = glamor_setup_program_render(op, src, glyph_pict, dst, + glyphs_program, + &glamor_facet_composite_glyphs_120, + glamor_priv->glyph_defines); + if (!prog) + goto bail_one; + v = glamor_glyph_start(screen, nglyph); + } + + /* Add the glyph + */ + + glyphs_queued++; + if (_X_LIKELY(glamor_glyph_use_130(glamor_priv))) { + v[0] = x - glyph->info.x; + v[1] = y - glyph->info.y; + v[2] = glyph_draw->width; + v[3] = glyph_draw->height; + v[4] = glyph_priv->x; + v[5] = glyph_priv->y; + v += 6; + } else { + v[0] = x - glyph->info.x; + v[1] = y - glyph->info.y; + v[2] = glyph_priv->x; + v[3] = glyph_priv->y; + v += 4; + + v[0] = x - glyph->info.x + glyph_draw->width; + v[1] = y - glyph->info.y; + v[2] = glyph_priv->x + glyph_draw->width; + v[3] = glyph_priv->y; + v += 4; + + v[0] = x - glyph->info.x + glyph_draw->width; + v[1] = y - glyph->info.y + glyph_draw->height; + v[2] = glyph_priv->x + glyph_draw->width; + v[3] = glyph_priv->y + glyph_draw->height; + v += 4; + + v[0] = x - glyph->info.x; + v[1] = y - glyph->info.y + glyph_draw->height; + v[2] = glyph_priv->x; + v[3] = glyph_priv->y + glyph_draw->height; + v += 4; + } + } + } + x += glyph->info.xOff; + y += glyph->info.yOff; + nglyph--; + } + } + + if (glyphs_queued) + glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued); + + return; +} + +static struct glamor_glyph_atlas * +glamor_alloc_glyph_atlas(ScreenPtr screen, int depth, CARD32 f) +{ + PictFormatPtr format; + struct glamor_glyph_atlas *glyph_atlas; + + format = PictureMatchFormat(screen, depth, f); + if (!format) + return NULL; + glyph_atlas = calloc (1, sizeof (struct glamor_glyph_atlas)); + if (!glyph_atlas) + return NULL; + glyph_atlas->format = format; + glyph_atlas->serial = 1; + + return glyph_atlas; +} + +Bool +glamor_composite_glyphs_init(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + if (!dixRegisterPrivateKey(&glamor_glyph_private_key, PRIVATE_PIXMAP, sizeof (struct glamor_glyph_private))) + return FALSE; + + /* Make glyph atlases of a reasonable size, but no larger than the maximum + * supported by the hardware + */ + glamor_priv->glyph_atlas_dim = MIN(DEFAULT_ATLAS_DIM, glamor_priv->max_fbo_size); + + /* Don't stick huge glyphs in the atlases */ + glamor_priv->glyph_max_dim = glamor_priv->glyph_atlas_dim / 8; + + glamor_priv->glyph_atlas_a = glamor_alloc_glyph_atlas(screen, 8, PICT_a8); + if (!glamor_priv->glyph_atlas_a) + return FALSE; + glamor_priv->glyph_atlas_argb = glamor_alloc_glyph_atlas(screen, 32, PICT_a8r8g8b8); + if (!glamor_priv->glyph_atlas_argb) { + free (glamor_priv->glyph_atlas_a); + return FALSE; + } + if (!glamor_glyphs_init_facet(screen)) + return FALSE; + return TRUE; +} + +static void +glamor_free_glyph_atlas(struct glamor_glyph_atlas *atlas) +{ + if (!atlas) + return; + if (atlas->atlas) + FreePicture(atlas->atlas, 0); + free (atlas); +} + +void +glamor_composite_glyphs_fini(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + glamor_glyphs_fini_facet(screen); + glamor_free_glyph_atlas(glamor_priv->glyph_atlas_a); + glamor_free_glyph_atlas(glamor_priv->glyph_atlas_argb); +} diff --git a/xserver/glamor/glamor_compositerects.c b/xserver/glamor/glamor_compositerects.c index 3b6b2ed07..885a6c065 100644 --- a/xserver/glamor/glamor_compositerects.c +++ b/xserver/glamor/glamor_compositerects.c @@ -57,7 +57,7 @@ _pixman_region_init_clipped_rectangles(pixman_region16_t * region, unsigned int i, j; if (num_rects > ARRAY_SIZE(stack_boxes)) { - boxes = malloc(sizeof(pixman_box16_t) * num_rects); + boxes = xallocarray(num_rects, sizeof(pixman_box16_t)); if (boxes == NULL) return FALSE; } @@ -246,7 +246,7 @@ glamor_composite_rectangles(CARD8 op, goto done; } else { - if (_X_LIKELY(priv->type != GLAMOR_TEXTURE_LARGE)) { + if (_X_LIKELY(glamor_pixmap_priv_is_small(priv))) { int error; source = CreateSolidPicture(0, color, &error); @@ -254,7 +254,7 @@ glamor_composite_rectangles(CARD8 op, goto done; if (glamor_composite_clipped_region(op, source, NULL, dst, - NULL, NULL, priv, + NULL, NULL, pixmap, ®ion, 0, 0, 0, 0, 0, 0)) goto done; } diff --git a/xserver/glamor/glamor_copy.c b/xserver/glamor/glamor_copy.c index 3320935f0..5fed89f0c 100644 --- a/xserver/glamor/glamor_copy.c +++ b/xserver/glamor/glamor_copy.c @@ -42,7 +42,7 @@ use_copyarea(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg) glBindTexture(GL_TEXTURE_2D, src->tex); glUniform2f(prog->fill_offset_uniform, args->dx, args->dy); - glUniform2f(prog->fill_size_uniform, src->width, src->height); + glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height); return TRUE; } @@ -51,9 +51,9 @@ static const glamor_facet glamor_facet_copyarea = { "copy_area", .vs_vars = "attribute vec2 primitive;\n", .vs_exec = (GLAMOR_POS(gl_Position, primitive.xy) - " fill_pos = (fill_offset + primitive.xy) / fill_size;\n"), + " fill_pos = (fill_offset + primitive.xy) * fill_size_inv;\n"), .fs_exec = " gl_FragColor = texture2D(sampler, fill_pos);\n", - .locations = glamor_program_location_fill, + .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos, .use = use_copyarea, }; @@ -71,7 +71,7 @@ use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg) glBindTexture(GL_TEXTURE_2D, src->tex); glUniform2f(prog->fill_offset_uniform, args->dx, args->dy); - glUniform2f(prog->fill_size_uniform, src->width, src->height); + glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height); glamor_set_color(dst, gc->fgPixel, prog->fg_uniform); glamor_set_color(dst, gc->bgPixel, prog->bg_uniform); @@ -134,13 +134,13 @@ static const glamor_facet glamor_facet_copyplane = { .version = 130, .vs_vars = "attribute vec2 primitive;\n", .vs_exec = (GLAMOR_POS(gl_Position, (primitive.xy)) - " fill_pos = (fill_offset + primitive.xy) / fill_size;\n"), + " fill_pos = (fill_offset + primitive.xy) * fill_size_inv;\n"), .fs_exec = (" uvec4 bits = uvec4(round(texture2D(sampler, fill_pos) * bitmul));\n" " if ((bits & bitplane) != uvec4(0,0,0,0))\n" " gl_FragColor = fg;\n" " else\n" " gl_FragColor = bg;\n"), - .locations = glamor_program_location_fill|glamor_program_location_fg|glamor_program_location_bg|glamor_program_location_bitplane, + .locations = glamor_program_location_fillsamp|glamor_program_location_fillpos|glamor_program_location_fg|glamor_program_location_bg|glamor_program_location_bitplane, .use = use_copyplane, }; @@ -212,7 +212,7 @@ glamor_copy_cpu_fbo(DrawablePtr src, if (gc && gc->alu != GXcopy) goto bail; - if (gc && !glamor_pm_is_solid(dst, gc->planemask)) + if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask)) goto bail; glamor_make_current(glamor_priv); @@ -262,7 +262,7 @@ glamor_copy_fbo_cpu(DrawablePtr src, if (gc && gc->alu != GXcopy) goto bail; - if (gc && !glamor_pm_is_solid(dst, gc->planemask)) + if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask)) goto bail; glamor_make_current(glamor_priv); @@ -307,7 +307,7 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap); - int src_box_x, src_box_y, dst_box_x, dst_box_y; + int src_box_index, dst_box_index; int dst_off_x, dst_off_y; int src_off_x, src_off_y; GLshort *v; @@ -315,12 +315,11 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, struct copy_args args; glamor_program *prog; const glamor_facet *copy_facet; - Bool set_scissor; int n; glamor_make_current(glamor_priv); - if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask)) + if (gc && !glamor_set_planemask(gc->depth, gc->planemask)) goto bail_ctx; if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy)) @@ -339,7 +338,7 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, if (!prog->prog) { if (!glamor_build_program(screen, prog, - copy_facet, NULL)) + copy_facet, NULL, NULL, NULL)) goto bail_ctx; } @@ -367,48 +366,37 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src, glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y); - set_scissor = src_priv->type == GLAMOR_TEXTURE_LARGE; - if (set_scissor) - glEnable(GL_SCISSOR_TEST); + glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(src_priv, src_box_x, src_box_y) { - BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_x, src_box_y); + glamor_pixmap_loop(src_priv, src_box_index) { + BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_index); args.dx = dx + src_off_x - src_box->x1; args.dy = dy + src_off_y - src_box->y1; - args.src = glamor_pixmap_fbo_at(src_priv, src_box_x, src_box_y); + args.src = glamor_pixmap_fbo_at(src_priv, src_box_index); if (!glamor_use_program(dst_pixmap, gc, prog, &args)) goto bail_ctx; - glamor_pixmap_loop(dst_priv, dst_box_x, dst_box_y) { - glamor_set_destination_drawable(dst, dst_box_x, dst_box_y, FALSE, FALSE, - prog->matrix_uniform, &dst_off_x, &dst_off_y); - - if (set_scissor) - glScissor(dst_off_x - args.dx, - dst_off_y - args.dy, - src_box->x2 - src_box->x1, - src_box->y2 - src_box->y1); - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - glDrawArrays(GL_QUADS, 0, nbox * 4); - else { - int i; - for (i = 0; i < nbox; i++) - glDrawArrays(GL_TRIANGLE_FAN, i*4, 4); - } + glamor_pixmap_loop(dst_priv, dst_box_index) { + glamor_set_destination_drawable(dst, dst_box_index, FALSE, FALSE, + prog->matrix_uniform, + &dst_off_x, &dst_off_y); + + glScissor(dst_off_x - args.dx, + dst_off_y - args.dy, + src_box->x2 - src_box->x1, + src_box->y2 - src_box->y1); + + glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox); } } - if (set_scissor) - glDisable(GL_SCISSOR_TEST); + glDisable(GL_SCISSOR_TEST); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisable(GL_COLOR_LOGIC_OP); return TRUE; bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); return FALSE; } @@ -432,7 +420,6 @@ glamor_copy_fbo_fbo_temp(DrawablePtr src, { ScreenPtr screen = dst->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); PixmapPtr tmp_pixmap; BoxRec bounds; int n; @@ -447,12 +434,11 @@ glamor_copy_fbo_fbo_temp(DrawablePtr src, */ glamor_make_current(glamor_priv); - if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask)) + if (gc && !glamor_set_planemask(gc->depth, gc->planemask)) goto bail_ctx; if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy)) goto bail_ctx; - glDisable(GL_COLOR_LOGIC_OP); /* Find the size of the area to copy */ @@ -521,7 +507,6 @@ bail: return FALSE; bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); return FALSE; } @@ -656,6 +641,9 @@ glamor_copy(DrawablePtr src, Pixel bitplane, void *closure) { + if (nbox == 0) + return; + if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure)) return; glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); @@ -709,39 +697,3 @@ glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_regio RegionUninit(&dst_region); } - -Bool -glamor_copy_n_to_n_nf(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, - void *closure) -{ - if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure)) - return TRUE; - if (glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst)) - return FALSE; - glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); - return TRUE; -} - -Bool -glamor_copy_plane_nf(DrawablePtr src, DrawablePtr dst, GCPtr gc, - int srcx, int srcy, int w, int h, int dstx, int dsty, - unsigned long bitplane, RegionPtr *region) -{ - if (glamor_ddx_fallback_check_pixmap(src) && - glamor_ddx_fallback_check_pixmap(dst) && - glamor_ddx_fallback_check_gc(gc)) - return FALSE; - - *region = glamor_copy_plane(src, dst, gc, - srcx, srcy, w, h, dstx, dsty, - bitplane); - return TRUE; -} diff --git a/xserver/glamor/glamor_core.c b/xserver/glamor/glamor_core.c index 235a4baed..b9948b569 100644 --- a/xserver/glamor/glamor_core.c +++ b/xserver/glamor/glamor_core.c @@ -42,10 +42,9 @@ glamor_get_drawable_location(const DrawablePtr drawable) glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - if (pixmap_priv == NULL || - pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) + if (pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) return 'm'; - if (pixmap_priv->base.fbo->fb == glamor_priv->screen_fbo) + if (pixmap_priv->fbo->fb == glamor_priv->screen_fbo) return 's'; else return 'f'; @@ -88,6 +87,17 @@ glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...) GLint ok; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + if (glamor_priv->has_khr_debug) { + char *label; + va_list va; + + va_start(va, format); + XNFvasprintf(&label, format, va); + glObjectLabel(GL_PROGRAM, prog, -1, label); + free(label); + va_end(va); + } + glLinkProgram(prog); glGetProgramiv(prog, GL_LINK_STATUS, &ok); if (!ok) { @@ -101,17 +111,6 @@ glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...) ErrorF("Failed to link: %s\n", info); FatalError("GLSL link failure\n"); } - - if (glamor_priv->has_khr_debug) { - char *label; - va_list va; - - va_start(va, format); - XNFvasprintf(&label, format, va); - glObjectLabel(GL_PROGRAM, prog, -1, label); - free(label); - va_end(va); - } } /* @@ -173,46 +172,48 @@ glamor_init_finish_access_shaders(ScreenPtr screen) const char *fs_source = "void main()\n" "{\n" + " vec4 color = texture2D(sampler, source_texture);\n" " if (revert == REVERT_NONE) \n" " { \n" " if ((swap_rb != SWAP_NONE_DOWNLOADING) && (swap_rb != SWAP_NONE_UPLOADING)) \n" - " gl_FragColor = texture2D(sampler, source_texture).bgra;\n" + " gl_FragColor = color.bgra;\n" " else \n" - " gl_FragColor = texture2D(sampler, source_texture).rgba;\n" + " gl_FragColor = color.rgba;\n" " } \n" " else \n" " { \n" " if (swap_rb == SWAP_DOWNLOADING) \n" - " gl_FragColor = texture2D(sampler, source_texture).argb;\n" + " gl_FragColor = color.argb;\n" " else if (swap_rb == SWAP_NONE_DOWNLOADING)\n" - " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" + " gl_FragColor = color.abgr;\n" " else if (swap_rb == SWAP_UPLOADING)\n" - " gl_FragColor = texture2D(sampler, source_texture).gbar;\n" + " gl_FragColor = color.gbar;\n" " else if (swap_rb == SWAP_NONE_UPLOADING)\n" - " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" + " gl_FragColor = color.abgr;\n" " } \n" "}\n"; const char *set_alpha_source = "void main()\n" "{\n" + " vec4 color = texture2D(sampler, source_texture);\n" " if (revert == REVERT_NONE) \n" " { \n" " if ((swap_rb != SWAP_NONE_DOWNLOADING) && (swap_rb != SWAP_NONE_UPLOADING)) \n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n" + " gl_FragColor = vec4(color.bgr, 1);\n" " else \n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" + " gl_FragColor = vec4(color.rgb, 1);\n" " } \n" " else \n" " { \n" " if (swap_rb == SWAP_DOWNLOADING) \n" - " gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n" + " gl_FragColor = vec4(1, color.rgb);\n" " else if (swap_rb == SWAP_NONE_DOWNLOADING)\n" - " gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n" + " gl_FragColor = vec4(1, color.bgr);\n" " else if (swap_rb == SWAP_UPLOADING)\n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).gba, 1);\n" + " gl_FragColor = vec4(color.gba, 1);\n" " else if (swap_rb == SWAP_NONE_UPLOADING)\n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).abg, 1);\n" + " gl_FragColor = vec4(color.abg, 1);\n" " } \n" "}\n"; GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; @@ -281,18 +282,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glUniform1i(glamor_priv->finish_access_swap_rb[1], 0); } -void -glamor_fini_finish_access_shaders(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv; - - glamor_priv = glamor_get_screen_private(screen); - glamor_make_current(glamor_priv); - glDeleteProgram(glamor_priv->finish_access_prog[0]); - glDeleteProgram(glamor_priv->finish_access_prog[1]); -} - -GCOps glamor_gc_ops = { +static GCOps glamor_gc_ops = { .FillSpans = glamor_fill_spans, .SetSpans = glamor_set_spans, .PutImage = glamor_put_image, diff --git a/xserver/glamor/glamor_dash.c b/xserver/glamor/glamor_dash.c index e8f60fa10..a6a11c1a2 100644 --- a/xserver/glamor/glamor_dash.c +++ b/xserver/glamor/glamor_dash.c @@ -159,44 +159,42 @@ glamor_dash_setup(DrawablePtr drawable, GCPtr gc) &glamor_priv->on_off_dash_line_progs, &glamor_facet_on_off_dash_lines); if (!prog) - goto bail_ctx; + goto bail; break; case LineDoubleDash: if (gc->fillStyle != FillSolid) - goto bail_ctx; + goto bail; prog = &glamor_priv->double_dash_line_prog; if (!prog->prog) { if (!glamor_build_program(screen, prog, &glamor_facet_double_dash_lines, - NULL)) - goto bail_ctx; + NULL, NULL, NULL)) + goto bail; } if (!glamor_use_program(pixmap, gc, prog, NULL)) - goto bail_ctx; + goto bail; glamor_set_color(pixmap, gc->fgPixel, prog->fg_uniform); glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform); break; default: - goto bail_ctx; + goto bail; } /* Set the dash pattern as texture 1 */ glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, dash_priv->base.fbo->tex); + glBindTexture(GL_TEXTURE_2D, dash_priv->fbo->tex); glUniform1i(prog->dash_uniform, 1); glUniform1f(prog->dash_length_uniform, dash_pixmap->drawable.width); return prog; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return NULL; } @@ -207,16 +205,16 @@ glamor_dash_loop(DrawablePtr drawable, GCPtr gc, glamor_program *prog, { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - int box_x, box_y; + int box_index; int off_x, off_y; glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); - glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE, + glamor_set_destination_drawable(drawable, box_index, TRUE, TRUE, prog->matrix_uniform, &off_x, &off_y); while (nbox--) { @@ -230,7 +228,6 @@ glamor_dash_loop(DrawablePtr drawable, GCPtr gc, glamor_program *prog, } glDisable(GL_SCISSOR_TEST); - glDisable(GL_COLOR_LOGIC_OP); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); } diff --git a/xserver/glamor/glamor_egl.c b/xserver/glamor/glamor_egl.c index 6160032f0..80a97f7a1 100644 --- a/xserver/glamor/glamor_egl.c +++ b/xserver/glamor/glamor_egl.c @@ -187,7 +187,7 @@ glamor_egl_get_gbm_device(ScreenPtr screen) } unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h) +glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; @@ -200,6 +200,9 @@ glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h) glamor_egl = glamor_egl_get_screen_private(scrn); bo = gbm_bo_create(glamor_egl->gbm, w, h, GBM_FORMAT_ARGB8888, +#ifdef GLAMOR_HAS_GBM_LINEAR + (linear ? GBM_BO_USE_LINEAR : 0) | +#endif GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); if (!bo) return 0; @@ -239,7 +242,6 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) "Failed to create textured screen."); return FALSE; } - glamor_set_screen_pixmap(screen_pixmap, NULL); return TRUE; } @@ -272,7 +274,7 @@ glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image) glamor_get_pixmap_private(pixmap); EGLImageKHR old; - old = pixmap_priv->base.image; + old = pixmap_priv->image; if (old) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); @@ -280,7 +282,7 @@ glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image) eglDestroyImageKHR(glamor_egl->display, old); } - pixmap_priv->base.image = image; + pixmap_priv->image = image; } Bool @@ -393,48 +395,108 @@ glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name) } #endif -int -glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, - PixmapPtr pixmap, - unsigned int tex, - Bool want_name, CARD16 *stride, CARD32 *size) +static Bool +glamor_make_pixmap_exportable(PixmapPtr pixmap) { #ifdef GLAMOR_HAS_GBM + ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - struct glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - struct glamor_egl_screen_private *glamor_egl; - EGLImageKHR image; + unsigned width = pixmap->drawable.width; + unsigned height = pixmap->drawable.height; struct gbm_bo *bo; - int fd = -1; + PixmapPtr exported; + GCPtr scratch_gc; - EGLint attribs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_GL_TEXTURE_LEVEL_KHR, 0, - EGL_NONE - }; + if (pixmap_priv->image) + return TRUE; - glamor_egl = glamor_egl_get_screen_private(scrn); + if (pixmap->drawable.bitsPerPixel != 32) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make %dbpp pixmap exportable\n", + pixmap->drawable.bitsPerPixel); + return FALSE; + } - glamor_make_current(glamor_priv); + bo = gbm_bo_create(glamor_egl->gbm, width, height, + GBM_FORMAT_ARGB8888, +#ifdef GLAMOR_HAS_GBM_LINEAR + (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ? + GBM_BO_USE_LINEAR : 0) | +#endif + GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); + if (!bo) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make %dx%dx%dbpp GBM bo\n", + width, height, pixmap->drawable.bitsPerPixel); + return FALSE; + } - image = pixmap_priv->base.image; - if (!image) { - image = eglCreateImageKHR(glamor_egl->display, - glamor_egl->context, - EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (uintptr_t) - tex, attribs); - if (image == EGL_NO_IMAGE_KHR) - goto failure; - - glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); - glamor_egl_set_pixmap_image(pixmap, image); + exported = screen->CreatePixmap(screen, 0, 0, pixmap->drawable.depth, 0); + screen->ModifyPixmapHeader(exported, width, height, 0, 0, + gbm_bo_get_stride(bo), NULL); + if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make %dx%dx%dbpp pixmap from GBM bo\n", + width, height, pixmap->drawable.bitsPerPixel); + screen->DestroyPixmap(exported); + gbm_bo_destroy(bo); + return FALSE; } + gbm_bo_destroy(bo); + + scratch_gc = GetScratchGC(pixmap->drawable.depth, screen); + ValidateGC(&pixmap->drawable, scratch_gc); + scratch_gc->ops->CopyArea(&pixmap->drawable, &exported->drawable, + scratch_gc, + 0, 0, width, height, 0, 0); + FreeScratchGC(scratch_gc); + + /* Now, swap the tex/gbm/EGLImage/etc. of the exported pixmap into + * the original pixmap struct. + */ + glamor_egl_exchange_buffers(pixmap, exported); + + screen->DestroyPixmap(exported); + + return TRUE; +#else + return FALSE; +#endif +} + +void * +glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) +{ + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + struct glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + + if (!glamor_make_pixmap_exportable(pixmap)) + return NULL; + + return gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, + pixmap_priv->image, 0); +} - bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); +int +glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, + PixmapPtr pixmap, + unsigned int tex, + Bool want_name, CARD16 *stride, CARD32 *size) +{ +#ifdef GLAMOR_HAS_GBM + struct glamor_egl_screen_private *glamor_egl; + struct gbm_bo *bo; + int fd = -1; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + + bo = glamor_gbm_bo_from_pixmap(screen, pixmap); if (!bo) goto failure; @@ -459,72 +521,67 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, #endif } -_X_EXPORT PixmapPtr -glamor_pixmap_from_fd(ScreenPtr screen, - int fd, - CARD16 width, - CARD16 height, - CARD16 stride, CARD8 depth, CARD8 bpp) +_X_EXPORT Bool +glamor_back_pixmap_from_fd(PixmapPtr pixmap, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, CARD8 depth, CARD8 bpp) { #ifdef GLAMOR_HAS_GBM + ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; struct gbm_bo *bo; - EGLImageKHR image; - PixmapPtr pixmap; - Bool ret = FALSE; - - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, - EGL_DMA_BUF_PLANE0_FD_EXT, 0, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, - EGL_DMA_BUF_PLANE0_PITCH_EXT, 0, - EGL_NONE - }; + struct gbm_import_fd_data import_data = { 0 }; + Bool ret; glamor_egl = glamor_egl_get_screen_private(scrn); if (!glamor_egl->dri3_capable) - return NULL; + return FALSE; if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 || height == 0) - return NULL; - - attribs[1] = width; - attribs[3] = height; - attribs[7] = fd; - attribs[11] = stride; - image = eglCreateImageKHR(glamor_egl->display, - EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, - NULL, attribs); - - if (image == EGL_NO_IMAGE_KHR) - return NULL; - - /* EGL_EXT_image_dma_buf_import can impose restrictions on the - * usage of the image. Use gbm_bo to bypass the limitations. */ - - bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); - eglDestroyImageKHR(glamor_egl->display, image); + return FALSE; + import_data.fd = fd; + import_data.width = width; + import_data.height = height; + import_data.stride = stride; + import_data.format = GBM_FORMAT_ARGB8888; + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD, &import_data, 0); if (!bo) - return NULL; + return FALSE; - pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL); ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); gbm_bo_destroy(bo); + return ret; +#else + return FALSE; +#endif +} - if (ret) - return pixmap; - else { +_X_EXPORT PixmapPtr +glamor_pixmap_from_fd(ScreenPtr screen, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, CARD8 depth, CARD8 bpp) +{ +#ifdef GLAMOR_HAS_GBM + PixmapPtr pixmap; + Bool ret; + + pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); + ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height, + stride, depth, bpp); + if (ret == FALSE) { screen->DestroyPixmap(pixmap); return NULL; } + return pixmap; #else return NULL; #endif @@ -536,17 +593,13 @@ glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv && pixmap_priv->base.image) { + if (pixmap_priv->image) { ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); - /* Before destroy an image which was attached to - * a texture. we must call glFlush to make sure the - * operation on that texture has been done.*/ - glamor_block_handler(pixmap->drawable.pScreen); - eglDestroyImageKHR(glamor_egl->display, pixmap_priv->base.image); - pixmap_priv->base.image = NULL; + eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image); + pixmap_priv->image = NULL; } } @@ -561,13 +614,12 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) glamor_pixmap_exchange_fbos(front, back); - temp = back_priv->base.image; - back_priv->base.image = front_priv->base.image; - front_priv->base.image = temp; + temp = back_priv->image; + back_priv->image = front_priv->image; + front_priv->image = temp; glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM); - } void @@ -589,8 +641,8 @@ glamor_egl_close_screen(ScreenPtr screen) screen_pixmap = screen->GetScreenPixmap(screen); pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - eglDestroyImageKHR(glamor_egl->display, pixmap_priv->base.image); - pixmap_priv->base.image = NULL; + eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image); + pixmap_priv->image = NULL; screen->CloseScreen = glamor_egl->saved_close_screen; @@ -699,6 +751,21 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) #endif } +static void glamor_egl_cleanup(struct glamor_egl_screen_private *glamor_egl) +{ + if (glamor_egl->display != EGL_NO_DISPLAY) { + eglMakeCurrent(glamor_egl->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglTerminate(glamor_egl->display); + } +#ifdef GLAMOR_HAS_GBM + if (glamor_egl->gbm) + gbm_device_destroy(glamor_egl->gbm); +#endif + free(glamor_egl->device_path); + free(glamor_egl); +} + static void glamor_egl_free_screen(ScrnInfoPtr scrn) { @@ -706,17 +773,8 @@ glamor_egl_free_screen(ScrnInfoPtr scrn) glamor_egl = glamor_egl_get_screen_private(scrn); if (glamor_egl != NULL) { - - eglMakeCurrent(glamor_egl->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -#ifdef GLAMOR_HAS_GBM - if (glamor_egl->gbm) - gbm_device_destroy(glamor_egl->gbm); -#endif - free(glamor_egl->device_path); - scrn->FreeScreen = glamor_egl->saved_free_screen; - free(glamor_egl); + glamor_egl_cleanup(glamor_egl); scrn->FreeScreen(scrn); } } @@ -733,6 +791,15 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) #endif EGL_NONE }; + static const EGLint config_attribs_core[] = { + EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, + EGL_CONTEXT_MAJOR_VERSION_KHR, + GLAMOR_GL_CORE_VER_MAJOR, + EGL_CONTEXT_MINOR_VERSION_KHR, + GLAMOR_GL_CORE_VER_MINOR, + EGL_NONE + }; glamor_identify(0); glamor_egl = calloc(sizeof(*glamor_egl), 1); @@ -747,7 +814,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) glamor_egl->gbm = gbm_create_device(glamor_egl->fd); if (glamor_egl->gbm == NULL) { ErrorF("couldn't get display device\n"); - return FALSE; + goto error; } glamor_egl->display = eglGetDisplay(glamor_egl->gbm); #else @@ -764,7 +831,8 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) if (!eglInitialize (glamor_egl->display, &glamor_egl->major, &glamor_egl->minor)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n"); - return FALSE; + glamor_egl->display = EGL_NO_DISPLAY; + goto error; } version = eglQueryString(glamor_egl->display, EGL_VERSION); @@ -773,14 +841,14 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) #define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT)) { \ ErrorF("EGL_" #EXT " required.\n"); \ - return FALSE; \ + goto error; \ } #define GLAMOR_CHECK_EGL_EXTENSIONS(EXT1, EXT2) \ if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT1) && \ !epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT2)) { \ ErrorF("EGL_" #EXT1 " or EGL_" #EXT2 " required.\n"); \ - return FALSE; \ + goto error; \ } GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); @@ -792,28 +860,36 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) KHR_surfaceless_opengl); #endif -#ifdef GLAMOR_HAS_GBM - if (epoxy_has_egl_extension(glamor_egl->display, - "EGL_KHR_gl_texture_2D_image") && - epoxy_has_egl_extension(glamor_egl->display, - "EGL_EXT_image_dma_buf_import")) - glamor_egl->dri3_capable = TRUE; -#endif - +#ifndef GLAMOR_GLES2 glamor_egl->context = eglCreateContext(glamor_egl->display, NULL, EGL_NO_CONTEXT, - config_attribs); - if (glamor_egl->context == EGL_NO_CONTEXT) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n"); - return FALSE; + config_attribs_core); +#else + glamor_egl->context = NULL; +#endif + if (!glamor_egl->context) { + glamor_egl->context = eglCreateContext(glamor_egl->display, + NULL, EGL_NO_CONTEXT, + config_attribs); + if (glamor_egl->context == EGL_NO_CONTEXT) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n"); + 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"); - return FALSE; + goto error; } +#ifdef GLAMOR_HAS_GBM + if (epoxy_has_egl_extension(glamor_egl->display, + "EGL_KHR_gl_texture_2D_image") && + epoxy_has_gl_extension("GL_OES_EGL_image")) + glamor_egl->dri3_capable = TRUE; +#endif + glamor_egl->saved_free_screen = scrn->FreeScreen; scrn->FreeScreen = glamor_egl_free_screen; #ifdef GLAMOR_GLES2 @@ -823,6 +899,10 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) "Indirect GLX may not work correctly.\n"); #endif return TRUE; + +error: + glamor_egl_cleanup(glamor_egl); + return FALSE; } /** Stub to retain compatibility with pre-server-1.16 ABI. */ diff --git a/xserver/glamor/glamor_egl_stubs.c b/xserver/glamor/glamor_egl_stubs.c index a93f62dcb..5dbbfe4b2 100644 --- a/xserver/glamor/glamor_egl_stubs.c +++ b/xserver/glamor/glamor_egl_stubs.c @@ -48,9 +48,3 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, { return 0; } - -unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h) -{ - return 0; -} diff --git a/xserver/glamor/glamor_fbo.c b/xserver/glamor/glamor_fbo.c index 802d665a9..c6ba095c0 100644 --- a/xserver/glamor/glamor_fbo.c +++ b/xserver/glamor/glamor_fbo.c @@ -70,9 +70,26 @@ cache_hbucket(int size) return order; } +static int +cache_format(GLenum format) +{ + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_RED: + return 2; + case GL_RGB: + return 1; + case GL_RGBA: + return 0; + default: + return -1; + } +} + static glamor_pixmap_fbo * glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, int flag) + int w, int h, GLenum format) { struct xorg_list *cache; glamor_pixmap_fbo *fbo_entry, *ret_fbo = NULL; @@ -87,33 +104,18 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, cache = &glamor_priv->fbo_cache[n_format] [cache_wbucket(w)] [cache_hbucket(h)]; - if (!(flag & GLAMOR_CACHE_EXACT_SIZE)) { - xorg_list_for_each_entry(fbo_entry, cache, list) { - if (fbo_entry->width >= w && fbo_entry->height >= h) { - - DEBUGF("Request w %d h %d format %x \n", w, h, format); - DEBUGF("got cache entry %p w %d h %d fbo %d tex %d format %x\n", - fbo_entry, fbo_entry->width, fbo_entry->height, - fbo_entry->fb, fbo_entry->tex); - xorg_list_del(&fbo_entry->list); - ret_fbo = fbo_entry; - break; - } - } - } - else { - xorg_list_for_each_entry(fbo_entry, cache, list) { - if (fbo_entry->width == w && fbo_entry->height == h) { - - DEBUGF("Request w %d h %d format %x \n", w, h, format); - DEBUGF("got cache entry %p w %d h %d fbo %d tex %d format %x\n", - fbo_entry, fbo_entry->width, fbo_entry->height, - fbo_entry->fb, fbo_entry->tex, fbo_entry->format); - assert(format == fbo_entry->format); - xorg_list_del(&fbo_entry->list); - ret_fbo = fbo_entry; - break; - } + + xorg_list_for_each_entry(fbo_entry, cache, list) { + if (fbo_entry->width == w && fbo_entry->height == h) { + + DEBUGF("Request w %d h %d format %x \n", w, h, format); + DEBUGF("got cache entry %p w %d h %d fbo %d tex %d format %x\n", + fbo_entry, fbo_entry->width, fbo_entry->height, + fbo_entry->fb, fbo_entry->tex, fbo_entry->format); + assert(format == fbo_entry->format); + xorg_list_del(&fbo_entry->list); + ret_fbo = fbo_entry; + break; } } @@ -127,22 +129,22 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, } static void -glamor_purge_fbo(glamor_pixmap_fbo *fbo) +glamor_purge_fbo(glamor_screen_private *glamor_priv, + glamor_pixmap_fbo *fbo) { - glamor_make_current(fbo->glamor_priv); + glamor_make_current(glamor_priv); if (fbo->fb) glDeleteFramebuffers(1, &fbo->fb); if (fbo->tex) glDeleteTextures(1, &fbo->tex); - if (fbo->pbo) - glDeleteBuffers(1, &fbo->pbo); free(fbo); } static void -glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) +glamor_pixmap_fbo_cache_put(glamor_screen_private *glamor_priv, + glamor_pixmap_fbo *fbo) { struct xorg_list *cache; int n_format; @@ -154,32 +156,33 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) n_format = cache_format(fbo->format); if (fbo->fb == 0 || fbo->external || n_format == -1 - || fbo->glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) { - fbo->glamor_priv->tick += GLAMOR_CACHE_EXPIRE_MAX; - glamor_fbo_expire(fbo->glamor_priv); - glamor_purge_fbo(fbo); + || glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) { + glamor_priv->tick += GLAMOR_CACHE_EXPIRE_MAX; + glamor_fbo_expire(glamor_priv); + glamor_purge_fbo(glamor_priv, fbo); return; } - cache = &fbo->glamor_priv->fbo_cache[n_format] + cache = &glamor_priv->fbo_cache[n_format] [cache_wbucket(fbo->width)] [cache_hbucket(fbo->height)]; DEBUGF ("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, fbo->width, fbo->height, fbo->format, fbo->fb, fbo->tex); - fbo->glamor_priv->fbo_cache_watermark += fbo->width * fbo->height; + glamor_priv->fbo_cache_watermark += fbo->width * fbo->height; xorg_list_add(&fbo->list, cache); - fbo->expire = fbo->glamor_priv->tick + GLAMOR_CACHE_EXPIRE_MAX; + fbo->expire = glamor_priv->tick + GLAMOR_CACHE_EXPIRE_MAX; #endif } static int -glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) +glamor_pixmap_ensure_fb(glamor_screen_private *glamor_priv, + glamor_pixmap_fbo *fbo) { int status, err = 0; - glamor_make_current(fbo->glamor_priv); + glamor_make_current(glamor_priv); if (fbo->fb == 0) glGenFramebuffers(1, &fbo->fb); @@ -239,22 +242,17 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, fbo->height = h; fbo->external = FALSE; fbo->format = format; - fbo->glamor_priv = glamor_priv; - if (flag == GLAMOR_CREATE_PIXMAP_MAP) { - glamor_make_current(glamor_priv); - glGenBuffers(1, &fbo->pbo); - goto done; - } + if (flag == CREATE_PIXMAP_USAGE_SHARED) + fbo->external = TRUE; if (flag != GLAMOR_CREATE_FBO_NO_FBO) { - if (glamor_pixmap_ensure_fb(fbo) != 0) { - glamor_purge_fbo(fbo); + if (glamor_pixmap_ensure_fb(glamor_priv, fbo) != 0) { + glamor_purge_fbo(glamor_priv, fbo); fbo = NULL; } } - done: return fbo; } @@ -280,7 +278,7 @@ glamor_fbo_expire(glamor_screen_private *glamor_priv) xorg_list_del(&fbo_entry->list); DEBUGF("cache %p fbo %p expired %d current %d \n", cache, fbo_entry, fbo_entry->expire, glamor_priv->tick); - glamor_purge_fbo(fbo_entry); + glamor_purge_fbo(glamor_priv, fbo_entry); } } @@ -317,16 +315,17 @@ glamor_fini_pixmap_fbo(ScreenPtr screen) xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { xorg_list_del(&fbo_entry->list); - glamor_purge_fbo(fbo_entry); + glamor_purge_fbo(glamor_priv, fbo_entry); } } } void -glamor_destroy_fbo(glamor_pixmap_fbo *fbo) +glamor_destroy_fbo(glamor_screen_private *glamor_priv, + glamor_pixmap_fbo *fbo) { xorg_list_del(&fbo->list); - glamor_pixmap_fbo_cache_put(fbo); + glamor_pixmap_fbo_cache_put(glamor_priv, fbo); } @@ -334,25 +333,34 @@ static int _glamor_create_tex(glamor_screen_private *glamor_priv, int w, int h, GLenum format) { - unsigned int tex = 0; - - /* With dri3, we want to allocate ARGB8888 pixmaps only. - * Depending on the implementation, GL_RGBA might not - * give us ARGB8888. We ask glamor_egl to use get - * an ARGB8888 based texture for us. */ - if (format == GL_RGBA) { - tex = glamor_egl_create_argb8888_based_texture(glamor_priv->screen, - w, h); + unsigned int tex; + + 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) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ZERO); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED); } - if (!tex) { - 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); - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, - format, GL_UNSIGNED_BYTE, NULL); + glamor_priv->suppress_gl_out_of_memory_logging = true; + glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, + format, GL_UNSIGNED_BYTE, NULL); + glamor_priv->suppress_gl_out_of_memory_logging = false; + + if (glGetError() == GL_OUT_OF_MEMORY) { + if (!glamor_priv->logged_any_fbo_allocation_failure) { + LogMessageVerb(X_WARNING, 0, "glamor: Failed to allocate %dx%d " + "FBO due to GL_OUT_OF_MEMORY.\n", w, h); + LogMessageVerb(X_WARNING, 0, + "glamor: Expect reduced performance.\n"); + glamor_priv->logged_any_fbo_allocation_failure = true; + } + glDeleteTextures(1, &tex); + return 0; } + return tex; } @@ -362,45 +370,40 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, { glamor_pixmap_fbo *fbo; GLint tex = 0; - int cache_flag; - if (flag == GLAMOR_CREATE_FBO_NO_FBO) + if (flag == GLAMOR_CREATE_FBO_NO_FBO || flag == CREATE_PIXMAP_USAGE_SHARED) goto new_fbo; - if (flag == GLAMOR_CREATE_PIXMAP_MAP) - goto no_tex; - - /* Tiling from textures requires exact pixmap sizes. As we don't - * know which pixmaps will be used as tiles, just allocate - * everything at the requested size - */ - cache_flag = GLAMOR_CACHE_EXACT_SIZE; - - fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, format, cache_flag); + fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, format); if (fbo) return fbo; new_fbo: tex = _glamor_create_tex(glamor_priv, w, h, format); - no_tex: + if (!tex) + return NULL; fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag); return fbo; } -static glamor_pixmap_fbo * -_glamor_create_fbo_array(glamor_screen_private *glamor_priv, +/** + * Create storage for the w * h region, using FBOs of the GL's maximum + * supported size. + */ +glamor_pixmap_fbo * +glamor_create_fbo_array(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag, int block_w, int block_h, - glamor_pixmap_private *pixmap_priv, int has_fbo) + glamor_pixmap_private *priv) { int block_wcnt; int block_hcnt; glamor_pixmap_fbo **fbo_array; BoxPtr box_array; int i, j; - glamor_pixmap_private_large_t *priv; - priv = &pixmap_priv->large; + priv->block_w = block_w; + priv->block_h = block_h; block_wcnt = (w + block_w - 1) / block_w; block_hcnt = (h + block_h - 1) / block_h; @@ -431,13 +434,10 @@ _glamor_create_fbo_array(glamor_screen_private *glamor_priv, fbo_w = box_array[i * block_wcnt + j].x2 - box_array[i * block_wcnt + j].x1; - if (!has_fbo) - fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv, - fbo_w, fbo_h, - format, - GLAMOR_CREATE_PIXMAP_FIXUP); - else - fbo_array[i * block_wcnt + j] = priv->base.fbo; + fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv, + fbo_w, fbo_h, + format, + GLAMOR_CREATE_PIXMAP_FIXUP); if (fbo_array[i * block_wcnt + j] == NULL) goto cleanup; } @@ -452,27 +452,13 @@ _glamor_create_fbo_array(glamor_screen_private *glamor_priv, cleanup: for (i = 0; i < block_wcnt * block_hcnt; i++) - if ((fbo_array)[i]) - glamor_destroy_fbo((fbo_array)[i]); + if (fbo_array[i]) + glamor_destroy_fbo(glamor_priv, fbo_array[i]); free(box_array); free(fbo_array); return NULL; } -/* Create a fbo array to cover the w*h region, by using block_w*block_h - * block.*/ -glamor_pixmap_fbo * -glamor_create_fbo_array(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, int flag, - int block_w, int block_h, - glamor_pixmap_private *pixmap_priv) -{ - pixmap_priv->large.block_w = block_w; - pixmap_priv->large.block_h = block_h; - return _glamor_create_fbo_array(glamor_priv, w, h, format, flag, - block_w, block_h, pixmap_priv, 0); -} - glamor_pixmap_fbo * glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) { @@ -481,11 +467,11 @@ glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) if (pixmap_priv == NULL) return NULL; - fbo = pixmap_priv->base.fbo; + fbo = pixmap_priv->fbo; if (fbo == NULL) return NULL; - pixmap_priv->base.fbo = NULL; + pixmap_priv->fbo = NULL; return fbo; } @@ -497,47 +483,40 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv->base.fbo) + if (pixmap_priv->fbo) return; - pixmap_priv->base.fbo = fbo; + pixmap_priv->fbo = fbo; switch (pixmap_priv->type) { - case GLAMOR_TEXTURE_LARGE: case GLAMOR_TEXTURE_ONLY: case GLAMOR_TEXTURE_DRM: - pixmap_priv->base.gl_fbo = GLAMOR_FBO_NORMAL; - if (fbo->tex != 0) - pixmap_priv->base.gl_tex = 1; - else { - /* XXX For the Xephyr only, may be broken now. */ - pixmap_priv->base.gl_tex = 0; - } - case GLAMOR_MEMORY_MAP: + pixmap_priv->gl_fbo = GLAMOR_FBO_NORMAL; pixmap->devPrivate.ptr = NULL; - break; default: break; } } void -glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv) +glamor_pixmap_destroy_fbo(PixmapPtr pixmap) { + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); glamor_pixmap_fbo *fbo; - if (priv->type == GLAMOR_TEXTURE_LARGE) { + if (glamor_pixmap_priv_is_large(priv)) { int i; - glamor_pixmap_private_large_t *large = &priv->large; - for (i = 0; i < large->block_wcnt * large->block_hcnt; i++) - glamor_destroy_fbo(large->fbo_array[i]); - free(large->fbo_array); + for (i = 0; i < priv->block_wcnt * priv->block_hcnt; i++) + glamor_destroy_fbo(glamor_priv, priv->fbo_array[i]); + free(priv->fbo_array); } else { fbo = glamor_pixmap_detach_fbo(priv); if (fbo) - glamor_destroy_fbo(fbo); + glamor_destroy_fbo(glamor_priv, fbo); } } @@ -550,7 +529,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv->base.fbo == NULL) { + if (pixmap_priv->fbo == NULL) { fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, format, flag); @@ -561,13 +540,13 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) } else { /* We do have a fbo, but it may lack of fb or tex. */ - if (!pixmap_priv->base.fbo->tex) - pixmap_priv->base.fbo->tex = + if (!pixmap_priv->fbo->tex) + pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, format); - if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->base.fbo->fb == 0) - if (glamor_pixmap_ensure_fb(pixmap_priv->base.fbo) != 0) + if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0) + if (glamor_pixmap_ensure_fb(glamor_priv, pixmap_priv->fbo) != 0) return FALSE; } @@ -582,7 +561,7 @@ glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back) front_priv = glamor_get_pixmap_private(front); back_priv = glamor_get_pixmap_private(back); - temp_fbo = front_priv->base.fbo; - front_priv->base.fbo = back_priv->base.fbo; - back_priv->base.fbo = temp_fbo; + temp_fbo = front_priv->fbo; + front_priv->fbo = back_priv->fbo; + back_priv->fbo = temp_fbo; } diff --git a/xserver/glamor/glamor_font.c b/xserver/glamor/glamor_font.c index 6b3a16abc..637e0dce1 100644 --- a/xserver/glamor/glamor_font.c +++ b/xserver/glamor/glamor_font.c @@ -77,9 +77,25 @@ glamor_font_get(ScreenPtr screen, FontPtr font) glamor_font->glyph_width_bytes = glyph_width_bytes; glamor_font->glyph_height = glyph_height; - overall_width = glyph_width_bytes * num_cols; - overall_height = glyph_height * num_rows; + /* + * Layout the font two blocks of columns wide. + * This avoids a problem with some fonts that are too high to fit. + */ + glamor_font->row_width = glyph_width_bytes * num_cols; + + if (num_rows > 1) { + overall_width = glamor_font->row_width * 2; + overall_height = glyph_height * ((num_rows + 1) / 2); + } else { + overall_width = glamor_font->row_width; + overall_height = glyph_height; + } + if (overall_width > glamor_priv->max_fbo_size || + overall_height > glamor_priv->max_fbo_size) { + /* fallback if we don't fit inside a texture */ + return NULL; + } bits = malloc(overall_width * overall_height); if (!bits) return NULL; @@ -112,11 +128,17 @@ glamor_font_get(ScreenPtr screen, FontPtr font) (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); if (count) { - char *dst = bits + row * glyph_height * overall_width + - col * glyph_width_bytes; + char *dst; char *src = glyph->bits; unsigned y; + dst = bits; + /* get offset of start of first row */ + dst += (row / 2) * glyph_height * overall_width; + /* add offset into second row */ + dst += (row & 1) ? glamor_font->row_width : 0; + + dst += col * glyph_width_bytes; for (y = 0; y < GLYPHHEIGHTPIXELS(glyph); y++) { memcpy(dst, src, GLYPHWIDTHBYTES(glyph)); dst += overall_width; @@ -127,8 +149,13 @@ glamor_font_get(ScreenPtr screen, FontPtr font) } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glamor_priv->suppress_gl_out_of_memory_logging = true; glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, bits); + glamor_priv->suppress_gl_out_of_memory_logging = false; + if (glGetError() == GL_OUT_OF_MEMORY) + return NULL; free(bits); diff --git a/xserver/glamor/glamor_font.h b/xserver/glamor/glamor_font.h index 36d20624d..4d41e0196 100644 --- a/xserver/glamor/glamor_font.h +++ b/xserver/glamor/glamor_font.h @@ -30,7 +30,7 @@ typedef struct { CARD8 default_col; GLuint texture_id; - + GLuint row_width; CARD16 glyph_width_bytes; CARD16 glyph_width_pixels; CARD16 glyph_height; diff --git a/xserver/glamor/glamor_glyphblt.c b/xserver/glamor/glamor_glyphblt.c index 73b1df51e..b21aa068e 100644 --- a/xserver/glamor/glamor_glyphblt.c +++ b/xserver/glamor/glamor_glyphblt.c @@ -48,7 +48,7 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, glamor_pixmap_private *pixmap_priv; glamor_program *prog; RegionPtr clip = gc->pCompositeClip; - int box_x, box_y; + int box_index; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -60,14 +60,14 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, &glamor_priv->poly_glyph_blt_progs, &glamor_facet_poly_glyph_blt); if (!prog) - goto bail_ctx; + goto bail; glEnableVertexAttribArray(GLAMOR_VERTEX_POS); start_x += drawable->x; y += drawable->y; - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { int x; int n; int num_points, max_points; @@ -75,7 +75,7 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, int off_x, off_y; char *vbo_offset; - glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE, + glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y); max_points = 500; @@ -138,12 +138,9 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, } } - glDisable(GL_COLOR_LOGIC_OP); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); return TRUE; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } @@ -160,32 +157,6 @@ glamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc, ppci, pglyph_base); } -Bool -glamor_poly_glyph_blt_nf(DrawablePtr drawable, GCPtr gc, - int start_x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyph_base) -{ - if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, - pglyph_base)) - return TRUE; - if (glamor_ddx_fallback_check_pixmap(drawable) && - glamor_ddx_fallback_check_gc(gc)) { - return FALSE; - } - miPolyGlyphBlt(drawable, gc, start_x, y, nglyph, - ppci, pglyph_base); - return TRUE; -} - -Bool -glamor_image_glyph_blt_nf(DrawablePtr drawable, GCPtr gc, - int start_x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyph_base) -{ - miImageGlyphBlt(drawable, gc, start_x, y, nglyph, ppci, pglyph_base); - return TRUE; -} - static Bool glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap, DrawablePtr drawable, int w, int h, int x, int y) @@ -198,7 +169,7 @@ glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap, int bitmap_stride = bitmap->devKind; glamor_program *prog; RegionPtr clip = gc->pCompositeClip; - int box_x, box_y; + int box_index; int yy, xx; int num_points; INT16 *points = NULL; @@ -217,7 +188,7 @@ glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap, &glamor_priv->poly_glyph_blt_progs, &glamor_facet_poly_glyph_blt); if (!prog) - goto bail_ctx; + goto bail; glEnableVertexAttribArray(GLAMOR_VERTEX_POS); @@ -249,19 +220,16 @@ glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap, glamor_put_vbo_space(screen); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { - glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE, + glamor_pixmap_loop(pixmap_priv, box_index) { + glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, prog->matrix_uniform, NULL, NULL); glDrawArrays(GL_POINTS, 0, num_points); } - glDisable(GL_COLOR_LOGIC_OP); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); return TRUE; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } @@ -275,21 +243,3 @@ glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y); } - -Bool -glamor_push_pixels_nf(GCPtr gc, PixmapPtr bitmap, - DrawablePtr drawable, int w, int h, int x, int y) -{ - if (glamor_push_pixels_gl(gc, bitmap, drawable, w, h, x, y)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable) && - glamor_ddx_fallback_check_pixmap(&bitmap->drawable) && - glamor_ddx_fallback_check_gc(gc)) - { - return FALSE; - } - - miPushPixels(gc, bitmap, drawable, w, h, x, y); - return TRUE; -} diff --git a/xserver/glamor/glamor_glyphs.c b/xserver/glamor/glamor_glyphs.c deleted file mode 100644 index 1f1362487..000000000 --- a/xserver/glamor/glamor_glyphs.c +++ /dev/null @@ -1,1783 +0,0 @@ -/* - * Copyright © 2008 Red Hat, Inc. - * Partly based on code Copyright © 2000 SuSE, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Red Hat not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Red Hat makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Owen Taylor <otaylor@fishsoup.net> - * Based on code by: Keith Packard - */ - -#include <stdlib.h> - -#include "glamor_priv.h" - -#include <mipict.h> - -#if DEBUG_GLYPH_CACHE -#define DBG_GLYPH_CACHE(a) ErrorF a -#else -#define DBG_GLYPH_CACHE(a) -#endif - -/* Width of the pixmaps we use for the caches; this should be less than - * max texture size of the driver; this may need to actually come from - * the driver. - */ - -/* Maximum number of glyphs we buffer on the stack before flushing - * rendering to the mask or destination surface. - */ -#define GLYPH_BUFFER_SIZE 1024 - -typedef struct { - PicturePtr source; - glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE + 4]; - int count; -} glamor_glyph_buffer_t; - -struct glamor_glyph { - glamor_glyph_cache_t *cache; - uint16_t x, y; - uint16_t size, pos; - unsigned long long left_x1_map, left_x2_map; - unsigned long long right_x1_map, right_x2_map; /* Use to check real intersect or not. */ - Bool has_edge_map; - Bool cached; -}; - -typedef enum { - GLAMOR_GLYPH_SUCCESS, /* Glyph added to render buffer */ - GLAMOR_GLYPH_FAIL, /* out of memory, etc */ - GLAMOR_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */ -} glamor_glyph_cache_result_t; - -#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) -static DevPrivateKeyRec glamor_glyph_key; - -static inline struct glamor_glyph * -glamor_glyph_get_private(ScreenPtr screen, GlyphPtr glyph) -{ - struct glamor_glyph *privates = (struct glamor_glyph*)glyph->devPrivates; - - return &privates[screen->myNum]; -} - -/* - * Mask cache is located at the corresponding cache picture's last row. - * and is deadicated for the mask picture when do the glyphs_via_mask. - * - * As we split the glyphs list according to its overlapped or non-overlapped, - * we can reduce the length of glyphs to do the glyphs_via_mask to 2 or 3 - * glyphs one time for most cases. Thus it give us a case to allocate a - * small portion of the corresponding cache directly as the mask picture. - * Then we can rendering the glyphs to this mask picture, and latter we - * can accumulate the second steps, composite the mask to the dest with - * the other non-overlapped glyphs's rendering process. - * Another major benefit is we now only need to clear a relatively small mask - * region then before. It also make us implement a bunch mask picture clearing - * algorithm to avoid too frequently small region clearing. - * - * If there is no any overlapping, this method will not get performance gain. - * If there is some overlapping, then this algorithm can get about 15% performance - * gain. - */ - -static void -clear_mask_cache_bitmap(glamor_glyph_mask_cache_t *maskcache, - unsigned int clear_mask_bits) -{ - unsigned int i = 0; - BoxRec box[MASK_CACHE_WIDTH]; - int box_cnt = 0; - - assert((clear_mask_bits & ~MASK_CACHE_MASK) == 0); - for (i = 0; i < MASK_CACHE_WIDTH; i++) { - if (clear_mask_bits & (1 << i)) { - box[box_cnt].x1 = maskcache->mcache[i].x; - box[box_cnt].x2 = maskcache->mcache[i].x + MASK_CACHE_MAX_SIZE; - box[box_cnt].y1 = maskcache->mcache[i].y; - box[box_cnt].y2 = maskcache->mcache[i].y + MASK_CACHE_MAX_SIZE; - box_cnt++; - } - } - glamor_solid_boxes(maskcache->pixmap, box, box_cnt, 0); - maskcache->cleared_bitmap |= clear_mask_bits; -} - -static void -clear_mask_cache(glamor_glyph_mask_cache_t *maskcache) -{ - int x = 0; - int cnt = MASK_CACHE_WIDTH; - unsigned int i = 0; - struct glamor_glyph_mask_cache_entry *mce; - - glamor_solid(maskcache->pixmap, 0, CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, - MASK_CACHE_MAX_SIZE, 0); - mce = &maskcache->mcache[0]; - while (cnt--) { - mce->width = 0; - mce->height = 0; - mce->x = x; - mce->y = CACHE_PICTURE_SIZE; - mce->idx = i++; - x += MASK_CACHE_MAX_SIZE; - mce++; - } - maskcache->free_bitmap = MASK_CACHE_MASK; - maskcache->cleared_bitmap = MASK_CACHE_MASK; -} - -static int -find_continuous_bits(unsigned int bits, int bits_cnt, unsigned int *pbits_mask) -{ - int idx = 0; - unsigned int bits_mask; - - bits_mask = ((1LL << bits_cnt) - 1); - - if (_X_UNLIKELY(bits_cnt > 56)) { - while (bits) { - if ((bits & bits_mask) == bits_mask) { - *pbits_mask = bits_mask << idx; - return idx; - } - bits >>= 1; - idx++; - } - } - else { - idx = __fls(bits); - while (bits) { - unsigned int temp_bits; - - temp_bits = bits_mask << (idx - bits_cnt + 1); - if ((bits & temp_bits) == temp_bits) { - *pbits_mask = temp_bits; - return (idx - bits_cnt + 1); - } - /* Find first zero. And clear the tested bit. */ - bits &= ~(1LL << idx); - idx = __fls(~bits); - bits &= ~((1LL << idx) - 1); - idx--; - } - } - return -1; -} - -static struct glamor_glyph_mask_cache_entry * -get_mask_cache(glamor_glyph_mask_cache_t *maskcache, int blocks) -{ - int free_cleared_bit, idx = -1; - int retry_cnt = 0; - unsigned int bits_mask = 0; - - if (maskcache->free_bitmap == 0) - return NULL; - retry: - free_cleared_bit = maskcache->free_bitmap & maskcache->cleared_bitmap; - if (free_cleared_bit && blocks == 1) { - idx = __fls(free_cleared_bit); - bits_mask = 1 << idx; - } - else if (free_cleared_bit && blocks > 1) { - idx = find_continuous_bits(free_cleared_bit, blocks, &bits_mask); - } - - if (idx < 0) { - clear_mask_cache_bitmap(maskcache, maskcache->free_bitmap); - if (retry_cnt++ > 2) - return NULL; - goto retry; - } - - maskcache->cleared_bitmap &= ~bits_mask; - maskcache->free_bitmap &= ~bits_mask; - DEBUGF("get idx %d free %x clear %x \n", - idx, maskcache->free_bitmap, maskcache->cleared_bitmap); - return &maskcache->mcache[idx]; -} - -static void -put_mask_cache_bitmap(glamor_glyph_mask_cache_t *maskcache, - unsigned int bitmap) -{ - maskcache->free_bitmap |= bitmap; - DEBUGF("put bitmap %x free %x clear %x \n", - bitmap, maskcache->free_bitmap, maskcache->cleared_bitmap); -} - -static void -glamor_unrealize_glyph_caches(ScreenPtr pScreen) -{ - glamor_screen_private *glamor = glamor_get_screen_private(pScreen); - int i; - - if (!glamor->glyph_caches_realized) - return; - - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHE_FORMATS; i++) { - glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; - - if (cache->picture) - FreePicture(cache->picture, 0); - - if (cache->glyphs) - free(cache->glyphs); - - if (glamor->mask_cache[i]) - free(glamor->mask_cache[i]); - } - glamor->glyph_caches_realized = FALSE; -} - -void -glamor_glyphs_fini(ScreenPtr pScreen) -{ - glamor_unrealize_glyph_caches(pScreen); -} - -/* All caches for a single format share a single pixmap for glyph storage, - * allowing mixing glyphs of different sizes without paying a penalty - * for switching between source pixmaps. (Note that for a size of font - * right at the border between two sizes, we might be switching for almost - * every glyph.) - * - * This function allocates the storage pixmap, and then fills in the - * rest of the allocated structures for all caches with the given format. - */ - -Bool -glamor_realize_glyph_caches(ScreenPtr pScreen) -{ - glamor_screen_private *glamor = glamor_get_screen_private(pScreen); - - unsigned int formats[] = { - PIXMAN_a8, - PIXMAN_a8r8g8b8, - }; - int i; - - if (glamor->glyph_caches_realized) - return TRUE; - - memset(glamor->glyphCaches, 0, sizeof(glamor->glyphCaches)); - - for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { - glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; - PixmapPtr pixmap; - PicturePtr picture; - XID component_alpha; - int depth = PIXMAN_FORMAT_DEPTH(formats[i]); - int error; - PictFormatPtr pPictFormat = - PictureMatchFormat(pScreen, depth, formats[i]); - if (!pPictFormat) - goto bail; - - /* Now allocate the pixmap and picture */ - pixmap = pScreen->CreatePixmap(pScreen, - CACHE_PICTURE_SIZE, - CACHE_PICTURE_SIZE + MASK_CACHE_MAX_SIZE, - depth, GLAMOR_CREATE_NO_LARGE); - if (!pixmap) - goto bail; - - component_alpha = NeedsComponent(pPictFormat->format); - picture = CreatePicture(0, &pixmap->drawable, pPictFormat, - CPComponentAlpha, &component_alpha, - serverClient, &error); - - pScreen->DestroyPixmap(pixmap); - if (!picture) - goto bail; - - ValidatePicture(picture); - - cache->picture = picture; - cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE); - if (!cache->glyphs) - goto bail; - - cache->evict = rand() % GLYPH_CACHE_SIZE; - glamor->mask_cache[i] = calloc(1, sizeof(*glamor->mask_cache[i])); - glamor->mask_cache[i]->pixmap = pixmap; - clear_mask_cache(glamor->mask_cache[i]); - } - assert(i == GLAMOR_NUM_GLYPH_CACHE_FORMATS); - - glamor->glyph_caches_realized = TRUE; - return TRUE; - - bail: - glamor_unrealize_glyph_caches(pScreen); - return FALSE; -} - -/** - * Called by glamor_create_screen_resources() to set up the glyph cache. - * - * This was previously required to be called by the drivers, but not - * as of the xserver 1.16 ABI. - */ -Bool -glamor_glyphs_init(ScreenPtr pScreen) -{ - if (!dixRegisterPrivateKey(&glamor_glyph_key, - PRIVATE_GLYPH, - screenInfo.numScreens * sizeof(struct glamor_glyph))) - return FALSE; - - return TRUE; -} - -/* The most efficient thing to way to upload the glyph to the screen - * is to use CopyArea; glamor pixmaps are always offscreen. - */ -static void -glamor_glyph_cache_upload_glyph(ScreenPtr screen, - glamor_glyph_cache_t *cache, - GlyphPtr glyph, int x, int y) -{ - PicturePtr pGlyphPicture = GlyphPicture(glyph)[screen->myNum]; - PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; - PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; - PixmapPtr scratch; - BoxRec box; - GCPtr gc; - - gc = GetScratchGC(pCachePixmap->drawable.depth, screen); - if (!gc) - return; - - ValidateGC(&pCachePixmap->drawable, gc); - - scratch = pGlyphPixmap; - if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) { - - scratch = glamor_create_pixmap(screen, - glyph->info.width, - glyph->info.height, - pCachePixmap->drawable.depth, 0); - if (scratch) { - PicturePtr picture; - int error; - - picture = - CreatePicture(0, - &scratch->drawable, - PictureMatchFormat - (screen, - pCachePixmap->drawable.depth, - cache->picture->format), - 0, NULL, serverClient, &error); - if (picture) { - ValidatePicture(picture); - glamor_composite(PictOpSrc, - pGlyphPicture, - NULL, picture, - 0, 0, 0, 0, 0, - 0, glyph->info.width, glyph->info.height); - FreePicture(picture, 0); - } - } - else { - scratch = pGlyphPixmap; - } - } - - box.x1 = x; - box.y1 = y; - box.x2 = x + glyph->info.width; - box.y2 = y + glyph->info.height; - glamor_copy(&scratch->drawable, - &pCachePixmap->drawable, NULL, - &box, 1, -x, -y, FALSE, FALSE, 0, NULL); - if (scratch != pGlyphPixmap) - screen->DestroyPixmap(scratch); - - FreeScratchGC(gc); -} - -void -glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph) -{ - struct glamor_glyph *priv; - - /* Use Lookup in case we have not attached to this glyph. */ - priv = glamor_glyph_get_private(screen, glyph); - - if (priv->cached) - priv->cache->glyphs[priv->pos] = NULL; -} - -/* Cut and paste from render/glyph.c - probably should export it instead */ -static void -glamor_glyph_extents(int nlist, - GlyphListPtr list, GlyphPtr *glyphs, BoxPtr extents) -{ - int x1, x2, y1, y2; - int x, y, n; - - x1 = y1 = MAXSHORT; - x2 = y2 = MINSHORT; - x = y = 0; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) { - GlyphPtr glyph = *glyphs++; - int v; - - v = x - glyph->info.x; - if (v < x1) - x1 = v; - v += glyph->info.width; - if (v > x2) - x2 = v; - - v = y - glyph->info.y; - if (v < y1) - y1 = v; - v += glyph->info.height; - if (v > y2) - y2 = v; - - x += glyph->info.xOff; - y += glyph->info.yOff; - } - } - - extents->x1 = x1 < MINSHORT ? MINSHORT : x1; - extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2; - extents->y1 = y1 < MINSHORT ? MINSHORT : y1; - extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2; -} - -static void -glamor_glyph_priv_get_edge_map(GlyphPtr glyph, struct glamor_glyph *priv, - PicturePtr glyph_picture) -{ - PixmapPtr glyph_pixmap = (PixmapPtr) glyph_picture->pDrawable; - int j; - unsigned long long left_x1_map = 0, left_x2_map = 0; - unsigned long long right_x1_map = 0, right_x2_map = 0; - int bitsPerPixel; - int stride; - void *bits; - int width; - unsigned int left_x1_data = 0, left_x2_data = 0; - unsigned int right_x1_data = 0, right_x2_data = 0; - - bitsPerPixel = glyph_pixmap->drawable.bitsPerPixel; - stride = glyph_pixmap->devKind; - bits = glyph_pixmap->devPrivate.ptr; - width = glyph->info.width; - - if (glyph_pixmap->drawable.width < 2 - || !(glyph_pixmap->drawable.depth == 8 - || glyph_pixmap->drawable.depth == 1 - || glyph_pixmap->drawable.depth == 32)) { - priv->has_edge_map = FALSE; - return; - } - - left_x1_map = left_x2_map = 0; - right_x1_map = right_x2_map = 0; - - for (j = 0; j < glyph_pixmap->drawable.height; j++) { - if (bitsPerPixel == 8) { - unsigned char *data; - - data = (unsigned char *) ((unsigned char *) bits + stride * j); - left_x1_data = *data++; - left_x2_data = *data; - data = - (unsigned char *) ((unsigned char *) bits + stride * j + width - - 2); - right_x1_data = *data++; - right_x2_data = *data; - } - else if (bitsPerPixel == 32) { - left_x1_data = *((unsigned int *) bits + stride / 4 * j); - left_x2_data = *((unsigned int *) bits + stride / 4 * j + 1); - right_x1_data = - *((unsigned int *) bits + stride / 4 * j + width - 2); - right_x2_data = - *((unsigned int *) bits + stride / 4 * j + width - 1); - } - else if (bitsPerPixel == 1) { - unsigned char temp; - - temp = *((unsigned char *) glyph_pixmap->devPrivate.ptr - + glyph_pixmap->devKind * j) & 0x3; - left_x1_data = temp & 0x1; - left_x2_data = temp & 0x2; - - temp = *((unsigned char *) glyph_pixmap->devPrivate.ptr - + glyph_pixmap->devKind * j - + (glyph_pixmap->drawable.width - 2) / 8); - right_x1_data = temp - & (1 << ((glyph_pixmap->drawable.width - 2) % 8)); - temp = *((unsigned char *) glyph_pixmap->devPrivate.ptr - + glyph_pixmap->devKind * j - + (glyph_pixmap->drawable.width - 1) / 8); - right_x2_data = temp - & (1 << ((glyph_pixmap->drawable.width - 1) % 8)); - } - left_x1_map |= (left_x1_data != 0) << j; - left_x2_map |= (left_x2_data != 0) << j; - right_x1_map |= (right_x1_data != 0) << j; - right_x2_map |= (right_x2_data != 0) << j; - } - - priv->left_x1_map = left_x1_map; - priv->left_x2_map = left_x2_map; - priv->right_x1_map = right_x1_map; - priv->right_x2_map = right_x2_map; - priv->has_edge_map = TRUE; - return; -} - -/** - * Returns TRUE if the glyphs in the lists intersect. Only checks based on - * bounding box, which appears to be good enough to catch most cases at least. - */ - -#define INTERSECTED_TYPE_MASK 1 -#define NON_INTERSECTED 0 -#define INTERSECTED 1 - -struct glamor_glyph_list { - int nlist; - GlyphListPtr list; - GlyphPtr *glyphs; - int type; -}; - -static Bool -glyph_new_fixed_list(struct glamor_glyph_list *fixed_list, - GlyphPtr *cur_glyphs, - GlyphPtr ** head_glyphs, - GlyphListPtr cur_list, - int cur_pos, int cur_x, int cur_y, - int x1, int y1, int x2, int y2, - GlyphListPtr *head_list, - int *head_pos, - int *head_x, - int *head_y, int *fixed_cnt, int type, BoxPtr prev_extents) -{ - int x_off = 0; - int y_off = 0; - int n_off = 0; - int list_cnt; - - if (type == NON_INTERSECTED) { - if (x1 < prev_extents->x2 && x2 > prev_extents->x1 - && y1 < prev_extents->y2 && y2 > prev_extents->y1) - return FALSE; - x_off = (*(cur_glyphs - 1))->info.xOff; - y_off = (*(cur_glyphs - 1))->info.yOff; - n_off = 1; - } - - list_cnt = cur_list - *head_list + 1; - if (cur_pos <= n_off) { - DEBUGF("break at %d n_off %d\n", cur_pos, n_off); - list_cnt--; - if (cur_pos < n_off) { - /* we overlap with previous list's last glyph. */ - x_off += cur_list->xOff; - y_off += cur_list->yOff; - cur_list--; - cur_pos = cur_list->len; - if (cur_pos <= n_off) { - list_cnt--; - } - } - } - DEBUGF("got %d lists\n", list_cnt); - if (list_cnt != 0) { - fixed_list->list = malloc(list_cnt * sizeof(*cur_list)); - memcpy(fixed_list->list, *head_list, list_cnt * sizeof(*cur_list)); - fixed_list->list[0].xOff = *head_x; - fixed_list->list[0].yOff = *head_y; - fixed_list->glyphs = *head_glyphs; - fixed_list->type = type & INTERSECTED_TYPE_MASK; - fixed_list->nlist = list_cnt; - if (cur_list != *head_list) { - fixed_list->list[0].len = (*head_list)->len - *head_pos; - if (cur_pos != n_off) - fixed_list->list[list_cnt - 1].len = cur_pos - n_off; - } - else - fixed_list->list[0].len = cur_pos - *head_pos - n_off; - (*fixed_cnt)++; - } - - if (type <= INTERSECTED) { - *head_list = cur_list; - *head_pos = cur_pos - n_off; - *head_x = cur_x - x_off; - *head_y = cur_y - y_off; - *head_glyphs = cur_glyphs - n_off; - } - return TRUE; -} - -/* - * This function detects glyph lists's overlapping. - * - * If check_fake_overlap is set, then it will check the glyph's left - * and right small boxes's real overlapping pixels. And if there is - * no real pixel overlapping, then it will not be treated as overlapped - * case. And we also can configured it to ignore less than 2 pixels - * overlappig. - * - * This function analyzes all the lists and split the list to multiple - * lists which are pure overlapped glyph lists or pure non-overlapped - * list if the overlapping only ocurr on the two adjacent glyphs. - * Otherwise, it return -1. - * - **/ - -static int -glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs, - PictFormatShort mask_format, - ScreenPtr screen, Bool check_fake_overlap, - struct glamor_glyph_list *fixed_list, int fixed_size) -{ - int x1, x2, y1, y2; - int n; - int x, y; - BoxPtr extents; - BoxRec prev_extents; - Bool first = TRUE, first_list = TRUE; - Bool need_free_list_region = FALSE; - Bool need_free_fixed_list = FALSE; - struct glamor_glyph *priv = NULL; - Bool in_non_intersected_list = -1; - GlyphListPtr head_list; - int head_x, head_y, head_pos; - int fixed_cnt = 0; - GlyphPtr *head_glyphs; - GlyphListPtr cur_list = list; - RegionRec list_region; - RegionRec current_region; - BoxRec current_box; - - if (nlist > 1) { - pixman_region_init(&list_region); - need_free_list_region = TRUE; - } - - pixman_region_init(¤t_region); - - extents = pixman_region_extents(¤t_region); - - x = 0; - y = 0; - x1 = x2 = y1 = y2 = 0; - n = 0; - extents->x1 = 0; - extents->y1 = 0; - extents->x2 = 0; - extents->y2 = 0; - - head_list = list; - DEBUGF("has %d lists.\n", nlist); - while (nlist--) { - BoxRec left_box, right_box = { 0 }; - Bool has_left_edge_box = FALSE, has_right_edge_box = FALSE; - Bool left_to_right; - struct glamor_glyph *left_priv = NULL, *right_priv = NULL; - - x += list->xOff; - y += list->yOff; - n = list->len; - left_to_right = TRUE; - cur_list = list++; - - if (_X_UNLIKELY(!first_list)) { - pixman_region_init_with_extents(¤t_region, extents); - pixman_region_union(&list_region, &list_region, ¤t_region); - first = TRUE; - } - else { - head_list = cur_list; - head_pos = cur_list->len - n; - head_x = x; - head_y = y; - head_glyphs = glyphs; - } - - DEBUGF("current list %p has %d glyphs\n", cur_list, n); - while (n--) { - GlyphPtr glyph = *glyphs++; - - DEBUGF("the %dth glyph\n", cur_list->len - n - 1); - if (glyph->info.width == 0 || glyph->info.height == 0) { - x += glyph->info.xOff; - y += glyph->info.yOff; - continue; - } - if (mask_format - && mask_format != GlyphPicture(glyph)[screen->myNum]->format) { - need_free_fixed_list = TRUE; - goto done; - } - - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - if (check_fake_overlap) - priv = glamor_glyph_get_private(screen, glyph); - - x2 = x1 + glyph->info.width; - y2 = y1 + glyph->info.height; - - if (x2 > MAXSHORT) - x2 = MAXSHORT; - if (y2 > MAXSHORT) - y2 = MAXSHORT; - - if (first) { - extents->x1 = x1; - extents->y1 = y1; - extents->x2 = x2; - extents->y2 = y2; - - prev_extents = *extents; - - first = FALSE; - if (check_fake_overlap && priv - && priv->has_edge_map && glyph->info.yOff == 0) { - left_box.x1 = x1; - left_box.x2 = x1 + 1; - left_box.y1 = y1; - - right_box.x1 = x2 - 2; - right_box.x2 = x2 - 1; - right_box.y1 = y1; - left_priv = right_priv = priv; - has_left_edge_box = TRUE; - has_right_edge_box = TRUE; - } - } - else { - if (_X_UNLIKELY(!first_list)) { - current_box.x1 = x1; - current_box.y1 = y1; - current_box.x2 = x2; - current_box.y2 = y2; - if (pixman_region_contains_rectangle - (&list_region, ¤t_box) != PIXMAN_REGION_OUT) { - need_free_fixed_list = TRUE; - goto done; - } - } - - if (x1 < extents->x2 && x2 > extents->x1 - && y1 < extents->y2 && y2 > extents->y1) { - - if (check_fake_overlap && - (has_left_edge_box || has_right_edge_box) - && priv->has_edge_map && glyph->info.yOff == 0) { - int left_dx, right_dx; - unsigned long long intersected; - - left_dx = has_left_edge_box ? 1 : 0; - right_dx = has_right_edge_box ? 1 : 0; - if (x1 + 1 < extents->x2 - right_dx && - x2 - 1 > extents->x1 + left_dx) - goto real_intersected; - - if (left_to_right && has_right_edge_box) { - if (x1 == right_box.x1) { - intersected = - ((priv->left_x1_map & right_priv-> - right_x1_map) - | (priv->left_x2_map & right_priv-> - right_x2_map)); - if (intersected) - goto real_intersected; - } - else if (x1 == right_box.x2) { - intersected = - (priv->left_x1_map & right_priv-> - right_x2_map); - if (intersected) { -#ifdef GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK - /* tolerate with two pixels overlap. */ - intersected &= ~(1 << __fls(intersected)); - if ((intersected & (intersected - 1))) -#endif - goto real_intersected; - } - } - } - else if (!left_to_right && has_left_edge_box) { - if (x2 - 1 == left_box.x1) { - intersected = - (priv->right_x2_map & left_priv-> - left_x1_map); - if (intersected) { -#ifdef GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK - /* tolerate with two pixels overlap. */ - intersected &= ~(1 << __fls(intersected)); - if ((intersected & (intersected - 1))) -#endif - goto real_intersected; - } - } - else if (x2 - 1 == right_box.x2) { - if ((priv->right_x1_map & left_priv-> - left_x1_map) - || (priv->right_x2_map & left_priv-> - left_x2_map)) - goto real_intersected; - } - } - else { - if (x1 < extents->x2 && x1 + 2 > extents->x1) - goto real_intersected; - } - goto non_intersected; - } - else { - real_intersected: - DEBUGF("overlap with previous glyph.\n"); - if (in_non_intersected_list == 1) { - if (fixed_cnt >= fixed_size) { - need_free_fixed_list = TRUE; - goto done; - } - if (!glyph_new_fixed_list(&fixed_list[fixed_cnt], - glyphs - 1, - &head_glyphs, - cur_list, - cur_list->len - (n + 1), - x, y, x1, y1, x2, y2, - &head_list, &head_pos, - &head_x, &head_y, - &fixed_cnt, - NON_INTERSECTED, - &prev_extents)) { - need_free_fixed_list = TRUE; - goto done; - } - } - - in_non_intersected_list = 0; - - } - } - else { - non_intersected: - DEBUGF("doesn't overlap with previous glyph.\n"); - if (in_non_intersected_list == 0) { - if (fixed_cnt >= fixed_size) { - need_free_fixed_list = TRUE; - goto done; - } - if (!glyph_new_fixed_list(&fixed_list[fixed_cnt], - glyphs - 1, - &head_glyphs, - cur_list, - cur_list->len - (n + 1), x, y, - x1, y1, x2, y2, - &head_list, - &head_pos, - &head_x, - &head_y, &fixed_cnt, - INTERSECTED, &prev_extents)) { - need_free_fixed_list = TRUE; - goto done; - } - } - in_non_intersected_list = 1; - } - prev_extents = *extents; - } - - if (check_fake_overlap && priv - && priv->has_edge_map && glyph->info.yOff == 0) { - if (!has_left_edge_box || x1 < extents->x1) { - left_box.x1 = x1; - left_box.x2 = x1 + 1; - left_box.y1 = y1; - has_left_edge_box = TRUE; - left_priv = priv; - } - - if (!has_right_edge_box || x2 > extents->x2) { - right_box.x1 = x2 - 2; - right_box.x2 = x2 - 1; - right_box.y1 = y1; - has_right_edge_box = TRUE; - right_priv = priv; - } - } - - if (x1 < extents->x1) - extents->x1 = x1; - if (x2 > extents->x2) - extents->x2 = x2; - - if (y1 < extents->y1) - extents->y1 = y1; - if (y2 > extents->y2) - extents->y2 = y2; - - x += glyph->info.xOff; - y += glyph->info.yOff; - } - first_list = FALSE; - } - - if (in_non_intersected_list == 0 && fixed_cnt == 0) { - fixed_cnt = -1; - goto done; - } - - if ((in_non_intersected_list != -1 || head_pos != n) && (fixed_cnt > 0)) { - if (fixed_cnt >= fixed_size) { - need_free_fixed_list = TRUE; - goto done; - } - if (!glyph_new_fixed_list(&fixed_list[fixed_cnt], - glyphs - 1, - &head_glyphs, - cur_list, - cur_list->len - (n + 1), x, y, - x1, y1, x2, y2, - &head_list, - &head_pos, - &head_x, - &head_y, &fixed_cnt, - (!in_non_intersected_list) | 0x80, - &prev_extents)) { - need_free_fixed_list = TRUE; - goto done; - } - } - - done: - if (need_free_list_region) - pixman_region_fini(&list_region); - pixman_region_fini(¤t_region); - - if (need_free_fixed_list && fixed_cnt >= 0) { - while (fixed_cnt--) { - free(fixed_list[fixed_cnt].list); - } - } - - DEBUGF("Got %d fixed list \n", fixed_cnt); - return fixed_cnt; -} - -static inline unsigned int -glamor_glyph_size_to_count(int size) -{ - size /= GLYPH_MIN_SIZE; - return size * size; -} - -static inline unsigned int -glamor_glyph_count_to_mask(int count) -{ - return ~(count - 1); -} - -static inline unsigned int -glamor_glyph_size_to_mask(int size) -{ - return glamor_glyph_count_to_mask(glamor_glyph_size_to_count(size)); -} - -static PicturePtr -glamor_glyph_cache(glamor_screen_private *glamor, GlyphPtr glyph, int *out_x, - int *out_y) -{ - ScreenPtr screen = glamor->screen; - PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; - glamor_glyph_cache_t *cache = - &glamor->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != 0]; - struct glamor_glyph *priv = NULL, *evicted_priv = NULL; - int size, mask, pos, s; - - if (glyph->info.width > GLYPH_MAX_SIZE - || glyph->info.height > GLYPH_MAX_SIZE) - return NULL; - - for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2) - if (glyph->info.width <= size && glyph->info.height <= size) - break; - - s = glamor_glyph_size_to_count(size); - mask = glamor_glyph_count_to_mask(s); - pos = (cache->count + s - 1) & mask; - - priv = glamor_glyph_get_private(screen, glyph); - if (pos < GLYPH_CACHE_SIZE) { - cache->count = pos + s; - } - else { - for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) { - int i = cache->evict & glamor_glyph_size_to_mask(s); - GlyphPtr evicted = cache->glyphs[i]; - - if (evicted == NULL) - continue; - - evicted_priv = glamor_glyph_get_private(screen, evicted); - assert(evicted_priv->pos == i); - if (evicted_priv->size >= s) { - cache->glyphs[i] = NULL; - evicted_priv->cached = FALSE; - pos = cache->evict & glamor_glyph_size_to_mask(size); - } - else - evicted_priv = NULL; - break; - } - if (evicted_priv == NULL) { - int count = glamor_glyph_size_to_count(size); - - mask = glamor_glyph_count_to_mask(count); - pos = cache->evict & mask; - for (s = 0; s < count; s++) { - GlyphPtr evicted = cache->glyphs[pos + s]; - - if (evicted != NULL) { - - evicted_priv = glamor_glyph_get_private(screen, evicted); - - assert(evicted_priv->pos == pos + s); - evicted_priv->cached = FALSE; - cache->glyphs[pos + s] = NULL; - } - } - - } - /* And pick a new eviction position */ - cache->evict = rand() % GLYPH_CACHE_SIZE; - } - - cache->glyphs[pos] = glyph; - - priv->cache = cache; - priv->size = size; - priv->pos = pos; - s = pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * - (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE)); - priv->x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE; - priv->y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE; - for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) { - if (pos & 1) - priv->x += s; - if (pos & 2) - priv->y += s; - pos >>= 2; - } - - glamor_glyph_cache_upload_glyph(screen, cache, glyph, priv->x, priv->y); -#ifndef GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK - if (priv->has_edge_map == FALSE && glyph->info.width >= 2) - glamor_glyph_priv_get_edge_map(glyph, priv, glyph_picture); -#endif - priv->cached = TRUE; - - *out_x = priv->x; - *out_y = priv->y; - return cache->picture; -} - -typedef void (*glyphs_flush_func) (void *arg); -struct glyphs_flush_dst_arg { - CARD8 op; - PicturePtr src; - PicturePtr dst; - glamor_glyph_buffer_t *buffer; - int x_src, y_src; - int x_dst, y_dst; -}; - -static struct glyphs_flush_dst_arg dst_arg; -static struct glyphs_flush_mask_arg mask_arg; -static glamor_glyph_buffer_t dst_buffer; -static glamor_glyph_buffer_t mask_buffer; -unsigned long long mask_glyphs_cnt = 0; -unsigned long long dst_glyphs_cnt = 0; - -#define GLYPHS_DST_MODE_VIA_MASK 0 -#define GLYPHS_DST_MODE_VIA_MASK_CACHE 1 -#define GLYPHS_DST_MODE_TO_DST 2 -#define GLYPHS_DST_MODE_MASK_TO_DST 3 - -struct glyphs_flush_mask_arg { - PicturePtr mask; - glamor_glyph_buffer_t *buffer; - glamor_glyph_mask_cache_t *maskcache; - unsigned int used_bitmap; -}; - -static void -glamor_glyphs_flush_mask(struct glyphs_flush_mask_arg *arg) -{ - if (arg->buffer->count > 0) { -#ifdef RENDER - glamor_composite_glyph_rects(PictOpAdd, arg->buffer->source, - NULL, arg->mask, - arg->buffer->count, arg->buffer->rects); -#endif - } - arg->buffer->count = 0; - arg->buffer->source = NULL; - -} - -static void -glamor_glyphs_flush_dst(struct glyphs_flush_dst_arg *arg) -{ - if (!arg->buffer) - return; - - if (mask_buffer.count > 0) { - glamor_glyphs_flush_mask(&mask_arg); - } - if (mask_arg.used_bitmap) { - put_mask_cache_bitmap(mask_arg.maskcache, mask_arg.used_bitmap); - mask_arg.used_bitmap = 0; - } - - if (arg->buffer->count > 0) { - glamor_composite_glyph_rects(arg->op, arg->src, - arg->buffer->source, arg->dst, - arg->buffer->count, - &arg->buffer->rects[0]); - arg->buffer->count = 0; - arg->buffer->source = NULL; - } -} - -static glamor_glyph_cache_result_t -glamor_buffer_glyph(glamor_screen_private *glamor_priv, - glamor_glyph_buffer_t *buffer, - PictFormatShort format, - GlyphPtr glyph, struct glamor_glyph *priv, - int x_glyph, int y_glyph, - int dx, int dy, int w, int h, - int glyphs_dst_mode, - glyphs_flush_func glyphs_flush, void *flush_arg) -{ - ScreenPtr screen = glamor_priv->screen; - glamor_composite_rect_t *rect; - PicturePtr source; - int x, y; - glamor_glyph_cache_t *cache; - - if (glyphs_dst_mode != GLYPHS_DST_MODE_MASK_TO_DST) - priv = glamor_glyph_get_private(screen, glyph); - - if (PICT_FORMAT_BPP(format) == 1) - format = PICT_a8; - - cache = &glamor_priv->glyphCaches[PICT_FORMAT_RGB(format) != 0]; - - if (buffer->source && buffer->source != cache->picture && glyphs_flush) { - (*glyphs_flush) (flush_arg); - glyphs_flush = NULL; - } - - if (buffer->count == GLYPH_BUFFER_SIZE && glyphs_flush) { - (*glyphs_flush) (flush_arg); - glyphs_flush = NULL; - } - - if (priv && priv->cached) { - rect = &buffer->rects[buffer->count++]; - rect->x_src = priv->x + dx; - rect->y_src = priv->y + dy; - if (buffer->source == NULL) - buffer->source = priv->cache->picture; - if (glyphs_dst_mode <= GLYPHS_DST_MODE_VIA_MASK_CACHE) - assert(priv->cache->glyphs[priv->pos] == glyph); - } - else { - assert(glyphs_dst_mode != GLYPHS_DST_MODE_MASK_TO_DST); - if (glyphs_flush) - (*glyphs_flush) (flush_arg); - source = glamor_glyph_cache(glamor_priv, glyph, &x, &y); - - if (source != NULL) { - rect = &buffer->rects[buffer->count++]; - rect->x_src = x + dx; - rect->y_src = y + dy; - if (buffer->source == NULL) - buffer->source = source; - if (glyphs_dst_mode == GLYPHS_DST_MODE_VIA_MASK_CACHE) { - /* mode 1 means we are using global mask cache, - * thus we have to composite from the cache picture - * to the cache picture, we need a flush here to make - * sure latter we get the corret glyphs data.*/ - glamor_make_current(glamor_priv); - glFlush(); - } - } - else { - /* Couldn't find the glyph in the cache, use the glyph picture directly */ - source = GlyphPicture(glyph)[screen->myNum]; - if (buffer->source && buffer->source != source && glyphs_flush) - (*glyphs_flush) (flush_arg); - buffer->source = source; - - rect = &buffer->rects[buffer->count++]; - rect->x_src = 0 + dx; - rect->y_src = 0 + dy; - } - priv = glamor_glyph_get_private(screen, glyph); - } - - rect->x_dst = x_glyph; - rect->y_dst = y_glyph; - if (glyphs_dst_mode != GLYPHS_DST_MODE_MASK_TO_DST) { - rect->x_dst -= glyph->info.x; - rect->y_dst -= glyph->info.y; - } - rect->width = w; - rect->height = h; - if (glyphs_dst_mode > GLYPHS_DST_MODE_VIA_MASK_CACHE) { - rect->x_mask = rect->x_src; - rect->y_mask = rect->y_src; - rect->x_src = dst_arg.x_src + rect->x_dst - dst_arg.x_dst; - rect->y_src = dst_arg.y_src + rect->y_dst - dst_arg.y_dst; - } - - return GLAMOR_GLYPH_SUCCESS; -} - -static void -glamor_buffer_glyph_clip(glamor_screen_private *glamor_priv, - BoxPtr rects, - int nrect, PictFormatShort format, - GlyphPtr glyph, struct glamor_glyph *priv, - int glyph_x, int glyph_y, - int glyph_dx, int glyph_dy, - int width, int height, - int glyphs_mode, - glyphs_flush_func flush_func, void *arg) -{ - int i; - - for (i = 0; i < nrect; i++) { - int dst_x, dst_y; - int dx, dy; - int x2, y2; - - dst_x = glyph_x - glyph_dx; - dst_y = glyph_y - glyph_dy; - x2 = dst_x + width; - y2 = dst_y + height; - dx = dy = 0; - if (rects[i].y1 >= y2) - break; - - if (dst_x < rects[i].x1) - dx = rects[i].x1 - dst_x, dst_x = rects[i].x1; - if (x2 > rects[i].x2) - x2 = rects[i].x2; - if (dst_y < rects[i].y1) - dy = rects[i].y1 - dst_y, dst_y = rects[i].y1; - if (y2 > rects[i].y2) - y2 = rects[i].y2; - if (dst_x < x2 && dst_y < y2) { - - glamor_buffer_glyph(glamor_priv, - &dst_buffer, - format, - glyph, priv, - dst_x + glyph_dx, - dst_y + glyph_dy, - dx, dy, - x2 - dst_x, y2 - dst_y, - glyphs_mode, flush_func, arg); - } - } -} - -static void -glamor_glyphs_via_mask(CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, - int nlist, GlyphListPtr list, GlyphPtr *glyphs, - Bool use_mask_cache) -{ - PixmapPtr mask_pixmap = 0; - PicturePtr mask; - ScreenPtr screen = dst->pDrawable->pScreen; - int width = 0, height = 0; - int x, y; - int x_dst = list->xOff, y_dst = list->yOff; - int n; - GlyphPtr glyph; - int error; - BoxRec extents = { 0, 0, 0, 0 }; - XID component_alpha; - glamor_screen_private *glamor_priv; - int need_free_mask = FALSE; - glamor_glyph_buffer_t buffer; - struct glyphs_flush_mask_arg arg; - glamor_glyph_buffer_t *pmask_buffer; - struct glyphs_flush_mask_arg *pmask_arg; - struct glamor_glyph_mask_cache_entry *mce = NULL; - glamor_glyph_mask_cache_t *maskcache; - glamor_glyph_cache_t *cache; - int glyphs_dst_mode; - - glamor_glyph_extents(nlist, list, glyphs, &extents); - - if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) - return; - glamor_priv = glamor_get_screen_private(screen); - width = extents.x2 - extents.x1; - height = extents.y2 - extents.y1; - - if (mask_format->depth == 1) { - PictFormatPtr a8Format = PictureMatchFormat(screen, 8, PICT_a8); - - if (a8Format) - mask_format = a8Format; - } - - cache = &glamor_priv->glyphCaches - [PICT_FORMAT_RGB(mask_format->format) != 0]; - maskcache = glamor_priv->mask_cache[PICT_FORMAT_RGB(mask_format->format) != 0]; - - x = -extents.x1; - y = -extents.y1; - if (!use_mask_cache || width > (CACHE_PICTURE_SIZE / 4) - || height > MASK_CACHE_MAX_SIZE) { - new_mask_pixmap: - mask_pixmap = glamor_create_pixmap(screen, width, height, - mask_format->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!mask_pixmap) { - glamor_destroy_pixmap(mask_pixmap); - return; - } - glamor_solid(mask_pixmap, 0, 0, width, height, 0); - component_alpha = NeedsComponent(mask_format->format); - mask = CreatePicture(0, &mask_pixmap->drawable, - mask_format, CPComponentAlpha, - &component_alpha, serverClient, &error); - if (!mask) - return; - need_free_mask = TRUE; - pmask_arg = &arg; - pmask_buffer = &buffer; - pmask_buffer->count = 0; - pmask_buffer->source = NULL; - pmask_arg->used_bitmap = 0; - glyphs_dst_mode = GLYPHS_DST_MODE_VIA_MASK; - } - else { - int retry_cnt = 0; - - retry: - mce = get_mask_cache(maskcache, - (width + MASK_CACHE_MAX_SIZE - - 1) / MASK_CACHE_MAX_SIZE); - - if (mce == NULL) { - glamor_glyphs_flush_dst(&dst_arg); - retry_cnt++; - if (retry_cnt > 2) { - assert(0); - goto new_mask_pixmap; - } - goto retry; - } - - mask = cache->picture; - x += mce->x; - y += mce->y; - mce->width = (width + MASK_CACHE_MAX_SIZE - 1) / MASK_CACHE_MAX_SIZE; - mce->height = 1; - if (mask_arg.mask && mask_arg.mask != mask && mask_buffer.count != 0) - glamor_glyphs_flush_dst(&dst_arg); - pmask_arg = &mask_arg; - pmask_buffer = &mask_buffer; - pmask_arg->maskcache = maskcache; - glyphs_dst_mode = GLYPHS_DST_MODE_VIA_MASK_CACHE; - } - pmask_arg->mask = mask; - pmask_arg->buffer = pmask_buffer; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - mask_glyphs_cnt += n; - while (n--) { - glyph = *glyphs++; - if (glyph->info.width > 0 && glyph->info.height > 0) { - glyphs_flush_func flush_func; - void *temp_arg; - - if (need_free_mask) { - if (pmask_buffer->count) - flush_func = - (glyphs_flush_func) glamor_glyphs_flush_mask; - else - flush_func = NULL; - temp_arg = pmask_arg; - } - else { - /* If we are using global mask cache, then we need to - * flush dst instead of mask. As some dst depends on the - * previous mask result. Just flush mask can't get all previous's - * overlapped glyphs.*/ - if (dst_buffer.count || mask_buffer.count) - flush_func = - (glyphs_flush_func) glamor_glyphs_flush_dst; - else - flush_func = NULL; - temp_arg = &dst_arg; - } - glamor_buffer_glyph(glamor_priv, pmask_buffer, - mask_format->format, - glyph, NULL, x, y, - 0, 0, - glyph->info.width, glyph->info.height, - glyphs_dst_mode, - flush_func, (void *) temp_arg); - } - x += glyph->info.xOff; - y += glyph->info.yOff; - } - list++; - } - - x = extents.x1; - y = extents.y1; - if (need_free_mask) { - glamor_glyphs_flush_mask(pmask_arg); - CompositePicture(op, - src, - mask, - dst, - x_src + x - x_dst, - y_src + y - y_dst, 0, 0, x, y, width, height); - FreePicture(mask, 0); - glamor_destroy_pixmap(mask_pixmap); - } - else { - struct glamor_glyph priv; - glyphs_flush_func flush_func; - BoxPtr rects; - int nrect; - - priv.cache = cache; - priv.x = mce->x; - priv.y = mce->y; - priv.cached = TRUE; - rects = REGION_RECTS(dst->pCompositeClip); - nrect = REGION_NUM_RECTS(dst->pCompositeClip); - - pmask_arg->used_bitmap |= ((1 << mce->width) - 1) << mce->idx; - dst_arg.op = op; - dst_arg.src = src; - dst_arg.dst = dst; - dst_arg.buffer = &dst_buffer; - dst_arg.x_src = x_src; - dst_arg.y_src = y_src; - dst_arg.x_dst = x_dst; - dst_arg.y_dst = y_dst; - - if (dst_buffer.source == NULL) { - dst_buffer.source = cache->picture; - } - else if (dst_buffer.source != cache->picture) { - glamor_glyphs_flush_dst(&dst_arg); - dst_buffer.source = cache->picture; - } - - x += dst->pDrawable->x; - y += dst->pDrawable->y; - - if (dst_buffer.count || mask_buffer.count) - flush_func = (glyphs_flush_func) glamor_glyphs_flush_dst; - else - flush_func = NULL; - - glamor_buffer_glyph_clip(glamor_priv, - rects, nrect, - mask_format->format, - NULL, &priv, - x, y, - 0, 0, - width, height, - GLYPHS_DST_MODE_MASK_TO_DST, - flush_func, (void *) &dst_arg); - } -} - -static void -glamor_glyphs_to_dst(CARD8 op, - PicturePtr src, - PicturePtr dst, - INT16 x_src, - INT16 y_src, - int nlist, GlyphListPtr list, GlyphPtr *glyphs) -{ - ScreenPtr screen = dst->pDrawable->pScreen; - int x = 0, y = 0; - int x_dst = list->xOff, y_dst = list->yOff; - int n; - GlyphPtr glyph; - BoxPtr rects; - int nrect; - glamor_screen_private *glamor_priv; - - rects = REGION_RECTS(dst->pCompositeClip); - nrect = REGION_NUM_RECTS(dst->pCompositeClip); - - glamor_priv = glamor_get_screen_private(screen); - - dst_arg.op = op; - dst_arg.src = src; - dst_arg.dst = dst; - dst_arg.buffer = &dst_buffer; - dst_arg.x_src = x_src; - dst_arg.y_src = y_src; - dst_arg.x_dst = x_dst; - dst_arg.y_dst = y_dst; - - x = dst->pDrawable->x; - y = dst->pDrawable->y; - - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - dst_glyphs_cnt += n; - while (n--) { - glyph = *glyphs++; - - if (glyph->info.width > 0 && glyph->info.height > 0) { - glyphs_flush_func flush_func; - - if (dst_buffer.count || mask_buffer.count) - flush_func = (glyphs_flush_func) glamor_glyphs_flush_dst; - else - flush_func = NULL; - glamor_buffer_glyph_clip(glamor_priv, - rects, nrect, - (GlyphPicture(glyph)[screen->myNum])-> - format, glyph, NULL, x, y, - glyph->info.x, glyph->info.y, - glyph->info.width, glyph->info.height, - GLYPHS_DST_MODE_TO_DST, flush_func, - (void *) &dst_arg); - } - - x += glyph->info.xOff; - y += glyph->info.yOff; - } - list++; - } -} - -#define MAX_FIXED_SIZE -static void -glamor_glyphs_reset_buffer(glamor_glyph_buffer_t *buffer) -{ - buffer->count = 0; - buffer->source = NULL; -} - -static Bool -_glamor_glyphs(CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, int nlist, GlyphListPtr list, - GlyphPtr *glyphs, Bool fallback) -{ - PictFormatShort format; - int fixed_size, fixed_cnt = 0; - struct glamor_glyph_list *fixed_list = NULL; - Bool need_free_list = FALSE; - -#ifndef GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK - Bool check_fake_overlap = TRUE; - - if (!(op == PictOpOver || op == PictOpAdd || op == PictOpXor)) { - /* C = (0,0,0,0) D = glyphs , SRC = A, DEST = B (faked overlapped glyphs, overlapped with (0,0,0,0)). - * For those op, (A IN (C ADD D)) OP B != (A IN D) OP ((A IN C) OP B) - * or (A IN (D ADD C)) OP B != (A IN C) OP ((A IN D) OP B) - * We need to split the faked regions to three or two, and composite the disoverlapped small - * boxes one by one. For other Ops, it's safe to composite the whole box. */ - check_fake_overlap = FALSE; - } -#else - Bool check_fake_overlap = FALSE; -#endif - if (mask_format) - format = mask_format->depth << 24 | mask_format->format; - else - format = 0; - - fixed_size = 32; - glamor_glyphs_reset_buffer(&dst_buffer); - - if (!mask_format || (((nlist == 1 && list->len == 1) || op == PictOpAdd) - && (dst->format == - ((mask_format->depth << 24) | mask_format-> - format)))) { - glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, list, glyphs); - goto last_flush; - } - - glamor_glyphs_reset_buffer(&mask_buffer); - - /* We have mask_format. Need to check the real overlap or not. */ - format = mask_format->depth << 24 | mask_format->format; - - fixed_list = calloc(fixed_size, sizeof(*fixed_list)); - if (_X_UNLIKELY(fixed_list == NULL)) - fixed_size = 0; - fixed_cnt = glamor_glyphs_intersect(nlist, list, glyphs, - format, dst->pDrawable->pScreen, - check_fake_overlap, - fixed_list, fixed_size); - if (fixed_cnt == 0) - mask_format = NULL; - need_free_list = TRUE; - - if (fixed_cnt <= 0) { - if (mask_format == NULL) { - glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, - list, glyphs); - goto last_flush; - } - else { - glamor_glyphs_via_mask(op, src, dst, mask_format, - x_src, y_src, nlist, list, glyphs, FALSE); - goto free_fixed_list; - } - } - else { - - /* We have splitted the original list to serval list, some are overlapped - * and some are non-overlapped. For the non-overlapped, we render it to - * dst directly. For the overlapped, we render it to mask picture firstly, - * then render the mask to dst. If we can use mask cache which is in the - * glyphs cache's last row, we can accumulate the rendering of mask to dst - * with the other dst_buffer's rendering operations thus can reduce the call - * of glDrawElements. - * - * */ - struct glamor_glyph_list *saved_list; - - saved_list = fixed_list; - mask_arg.used_bitmap = 0; - while (fixed_cnt--) { - if (fixed_list->type == NON_INTERSECTED) { - glamor_glyphs_to_dst(op, src, dst, - x_src, y_src, - fixed_list->nlist, - fixed_list->list, fixed_list->glyphs); - } - else - glamor_glyphs_via_mask(op, src, dst, - mask_format, x_src, y_src, - fixed_list->nlist, - fixed_list->list, - fixed_list->glyphs, TRUE); - - free(fixed_list->list); - fixed_list++; - } - free(saved_list); - need_free_list = FALSE; - } - - last_flush: - if (dst_buffer.count || mask_buffer.count) - glamor_glyphs_flush_dst(&dst_arg); - free_fixed_list: - if (need_free_list) { - assert(fixed_cnt <= 0); - free(fixed_list); - } - return TRUE; -} - -void -glamor_glyphs(CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr *glyphs) -{ - _glamor_glyphs(op, src, dst, mask_format, x_src, - y_src, nlist, list, glyphs, TRUE); -} - -Bool -glamor_glyphs_nf(CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr *glyphs) -{ - return _glamor_glyphs(op, src, dst, mask_format, x_src, - y_src, nlist, list, glyphs, FALSE); -} diff --git a/xserver/glamor/glamor_gradient.c b/xserver/glamor/glamor_gradient.c index 4ded89dcd..c50542a32 100644 --- a/xserver/glamor/glamor_gradient.c +++ b/xserver/glamor/glamor_gradient.c @@ -32,8 +32,6 @@ #include "glamor_priv.h" -#ifdef RENDER - #define LINEAR_SMALL_STOPS (6 + 2) #define LINEAR_LARGE_STOPS (16 + 2) @@ -584,27 +582,6 @@ glamor_init_gradient_shader(ScreenPtr screen) _glamor_create_radial_gradient_program(screen, RADIAL_LARGE_STOPS, 0); } -void -glamor_fini_gradient_shader(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv; - int i = 0; - - glamor_priv = glamor_get_screen_private(screen); - glamor_make_current(glamor_priv); - - for (i = 0; i < 3; i++) { - /* Linear Gradient */ - if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]) - glDeleteProgram(glamor_priv->gradient_prog - [SHADER_GRADIENT_LINEAR][i]); - - if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]) - glDeleteProgram(glamor_priv->gradient_prog - [SHADER_GRADIENT_RADIAL][i]); - } -} - static void _glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], int width, int height, int normalize) @@ -670,12 +647,12 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, PicturePtr dst_picture, GLfloat *xscale, GLfloat *yscale, int x_source, int y_source, - float vertices[8], - float tex_vertices[8], int tex_normalize) { glamor_pixmap_private *pixmap_priv; PixmapPtr pixmap = NULL; + GLfloat *v; + char *vbo_offset; pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable); pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -684,22 +661,24 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, return 0; } - glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_set_destination_pixmap_priv_nc(glamor_priv, pixmap, pixmap_priv); - pixmap_priv_get_dest_scale(pixmap_priv, xscale, yscale); + pixmap_priv_get_dest_scale(pixmap, pixmap_priv, xscale, yscale); DEBUGF("xscale = %f, yscale = %f," " x_source = %d, y_source = %d, width = %d, height = %d\n", *xscale, *yscale, x_source, y_source, dst_picture->pDrawable->width, dst_picture->pDrawable->height); + v = glamor_get_vbo_space(screen, 16 * sizeof(GLfloat), &vbo_offset); + glamor_set_normalize_vcoords_tri_strip(*xscale, *yscale, 0, 0, (INT16) (dst_picture->pDrawable-> width), (INT16) (dst_picture->pDrawable-> height), - vertices); + v); if (tex_normalize) { glamor_set_normalize_tcoords_tri_stripe(*xscale, *yscale, @@ -710,7 +689,7 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, (INT16) (dst_picture-> pDrawable->height + y_source), - tex_vertices); + &v[8]); } else { glamor_set_tcoords_tri_strip(x_source, y_source, @@ -718,28 +697,29 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, x_source, (INT16) (dst_picture->pDrawable->height) + y_source, - tex_vertices); + &v[8]); } DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," "rightbottom: %f X %f, leftbottom : %f X %f\n", - vertices[0], vertices[1], vertices[2], vertices[3], - vertices[4], vertices[5], vertices[6], vertices[7]); + v[0], v[1], v[2], v[3], + v[4], v[5], v[6], v[7]); DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," "rightbottom: %f X %f, leftbottom : %f X %f\n", - tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], - tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); + v[8], v[9], v[10], v[11], + v[12], v[13], v[14], v[15]); glamor_make_current(glamor_priv); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 0, vertices); + GL_FALSE, 0, vbo_offset); glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, - GL_FALSE, 0, tex_vertices); + GL_FALSE, 0, vbo_offset + 8 * sizeof(GLfloat)); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glamor_put_vbo_space(screen); return 1; } @@ -835,13 +815,11 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen, PixmapPtr pixmap = NULL; GLint gradient_prog = 0; int error; - float tex_vertices[8]; int stops_count = 0; int count = 0; GLfloat *stop_colors = NULL; GLfloat *n_stops = NULL; GLfloat xscale, yscale; - float vertices[8]; float transform_mat[3][3]; static const float identity_mat[3][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, @@ -992,18 +970,20 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen, if (!_glamor_gradient_set_pixmap_destination (screen, glamor_priv, dst_picture, &xscale, &yscale, x_source, y_source, - vertices, tex_vertices, 0)) + 0)) goto GRADIENT_FAIL; + glamor_set_alu(screen, GXcopy); + /* Set all the stops and colors to shader. */ if (stops_count > RADIAL_SMALL_STOPS) { - stop_colors = malloc(4 * stops_count * sizeof(float)); + stop_colors = xallocarray(stops_count, 4 * sizeof(float)); if (stop_colors == NULL) { ErrorF("Failed to allocate stop_colors memory.\n"); goto GRADIENT_FAIL; } - n_stops = malloc(stops_count * sizeof(float)); + n_stops = xallocarray(stops_count, sizeof(float)); if (n_stops == NULL) { ErrorF("Failed to allocate n_stops memory.\n"); goto GRADIENT_FAIL; @@ -1144,7 +1124,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, float pt_distance; float p1_distance; GLfloat cos_val; - float tex_vertices[8]; int stops_count = 0; GLfloat *stop_colors = NULL; GLfloat *n_stops = NULL; @@ -1152,7 +1131,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, float slope; GLfloat xscale, yscale; GLfloat pt1[2], pt2[2]; - float vertices[8]; float transform_mat[3][3]; static const float identity_mat[3][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, @@ -1308,9 +1286,11 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, if (!_glamor_gradient_set_pixmap_destination (screen, glamor_priv, dst_picture, &xscale, &yscale, x_source, y_source, - vertices, tex_vertices, 1)) + 1)) goto GRADIENT_FAIL; + glamor_set_alu(screen, GXcopy); + /* Normalize the PTs. */ glamor_set_normalize_pt(xscale, yscale, pixman_fixed_to_double(src_picture->pSourcePict-> @@ -1336,13 +1316,13 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, /* Set all the stops and colors to shader. */ if (stops_count > LINEAR_SMALL_STOPS) { - stop_colors = malloc(4 * stops_count * sizeof(float)); + stop_colors = xallocarray(stops_count, 4 * sizeof(float)); if (stop_colors == NULL) { ErrorF("Failed to allocate stop_colors memory.\n"); goto GRADIENT_FAIL; } - n_stops = malloc(stops_count * sizeof(float)); + n_stops = xallocarray(stops_count, sizeof(float)); if (n_stops == NULL) { ErrorF("Failed to allocate n_stops memory.\n"); goto GRADIENT_FAIL; @@ -1473,5 +1453,3 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, } #endif /* End of GLAMOR_GRADIENT_SHADER */ - -#endif /* End of RENDER */ diff --git a/xserver/glamor/glamor_image.c b/xserver/glamor/glamor_image.c index 90fda4079..315874995 100644 --- a/xserver/glamor/glamor_image.c +++ b/xserver/glamor/glamor_image.c @@ -49,7 +49,7 @@ glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (gc->alu != GXcopy) goto bail; - if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask)) + if (!glamor_pm_is_solid(gc->depth, gc->planemask)) goto bail; if (format == XYPixmap && drawable->depth == 1 && leftPad == 0) @@ -102,19 +102,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits); } -Bool -glamor_put_image_nf(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, - int w, int h, int leftPad, int format, char *bits) -{ - if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits)) - return TRUE; - if (glamor_ddx_fallback_check_pixmap(drawable) && - glamor_ddx_fallback_check_gc(gc)) - return FALSE; - glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits); - return TRUE; -} - static Bool glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h, unsigned int format, unsigned long plane_mask, char *d) @@ -129,7 +116,7 @@ glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h, if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto bail; - if (format != ZPixmap || !glamor_pm_is_solid(drawable, plane_mask)) + if (format != ZPixmap || !glamor_pm_is_solid(drawable->depth, plane_mask)) goto bail; glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); @@ -163,17 +150,3 @@ glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, return; glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d); } - -Bool -glamor_get_image_nf(DrawablePtr drawable, int x, int y, int w, int h, - unsigned int format, unsigned long plane_mask, char *d) -{ - if (glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable)) - return FALSE; - - glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d); - return TRUE; -} diff --git a/xserver/glamor/glamor_largepixmap.c b/xserver/glamor/glamor_largepixmap.c index b9c3b9af1..9a6c95ee9 100644 --- a/xserver/glamor/glamor_largepixmap.c +++ b/xserver/glamor/glamor_largepixmap.c @@ -2,10 +2,14 @@ #include "glamor_priv.h" -static inline glamor_pixmap_private_large_t * +static void +glamor_get_transform_extent_from_box(struct pixman_box32 *box, + struct pixman_transform *transform); + +static inline glamor_pixmap_private * __glamor_large(glamor_pixmap_private *pixmap_priv) { - assert(pixmap_priv->type == GLAMOR_TEXTURE_LARGE); - return &pixmap_priv->large; + assert(glamor_pixmap_priv_is_large(pixmap_priv)); + return pixmap_priv; } /** @@ -150,12 +154,13 @@ __glamor_compute_clipped_regions(int block_w, */ glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, +glamor_compute_clipped_regions_ext(PixmapPtr pixmap, RegionPtr region, int *n_region, int inner_block_w, int inner_block_h, int reverse, int upsidedown) { + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_pixmap_clipped_regions *clipped_regions, *inner_regions, *result_regions; int i, j, x, y, k, inner_n_regions; @@ -166,7 +171,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, DEBUGF("ext called \n"); - if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + if (glamor_pixmap_priv_is_small(pixmap_priv)) { clipped_regions = calloc(1, sizeof(*clipped_regions)); if (clipped_regions == NULL) { *n_region = 0; @@ -176,24 +181,22 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, clipped_regions[0].block_idx = 0; RegionCopy(clipped_regions[0].region, region); *n_region = 1; - block_w = pixmap_priv->base.pixmap->drawable.width; - block_h = pixmap_priv->base.pixmap->drawable.height; + block_w = pixmap->drawable.width; + block_h = pixmap->drawable.height; box_array = &small_box; small_box.x1 = small_box.y1 = 0; small_box.x2 = block_w; small_box.y2 = block_h; } else { - glamor_pixmap_private_large_t *priv = __glamor_large(pixmap_priv); + glamor_pixmap_private *priv = __glamor_large(pixmap_priv); clipped_regions = __glamor_compute_clipped_regions(priv->block_w, priv->block_h, priv->block_wcnt, 0, 0, - priv->base.pixmap-> - drawable.width, - priv->base.pixmap-> - drawable.height, + pixmap->drawable.width, + pixmap->drawable.height, region, n_region, reverse, upsidedown); @@ -336,7 +339,8 @@ _glamor_largepixmap_reflect_fixup(short *xy1, short *xy2, int wh) * */ static glamor_pixmap_clipped_regions * -_glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, +_glamor_compute_clipped_regions(PixmapPtr pixmap, + glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, int repeat_type, int is_transform, int reverse, int upsidedown) @@ -352,10 +356,10 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, int right_shift = 0; int down_shift = 0; int x_center_shift = 0, y_center_shift = 0; - glamor_pixmap_private_large_t *priv; + glamor_pixmap_private *priv; DEBUGRegionPrint(region); - if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + if (glamor_pixmap_priv_is_small(pixmap_priv)) { clipped_regions = calloc(1, sizeof(*clipped_regions)); clipped_regions[0].region = RegionCreate(NULL, 1); clipped_regions[0].block_idx = 0; @@ -366,8 +370,8 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, priv = __glamor_large(pixmap_priv); - pixmap_width = priv->base.pixmap->drawable.width; - pixmap_height = priv->base.pixmap->drawable.height; + pixmap_width = pixmap->drawable.width; + pixmap_height = pixmap->drawable.height; if (repeat_type == 0 || repeat_type == RepeatPad) { RegionPtr saved_region = NULL; @@ -385,10 +389,8 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, priv->block_h, priv->block_wcnt, 0, 0, - priv->base.pixmap-> - drawable.width, - priv->base.pixmap-> - drawable.height, + pixmap->drawable.width, + pixmap->drawable.height, region, n_region, reverse, upsidedown); if (saved_region) @@ -670,24 +672,27 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, } glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, +glamor_compute_clipped_regions(PixmapPtr pixmap, + RegionPtr region, int *n_region, int repeat_type, int reverse, int upsidedown) { - return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); + return _glamor_compute_clipped_regions(pixmap, priv, region, n_region, repeat_type, 0, reverse, upsidedown); } /* XXX overflow still exist. maybe we need to change to use region32. * by default. Or just use region32 for repeat cases? **/ -glamor_pixmap_clipped_regions * -glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, +static glamor_pixmap_clipped_regions * +glamor_compute_transform_clipped_regions(PixmapPtr pixmap, struct pixman_transform *transform, RegionPtr region, int *n_region, int dx, int dy, int repeat_type, int reverse, int upsidedown) { + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); BoxPtr temp_extent; struct pixman_box32 temp_box; struct pixman_box16 short_box; @@ -714,8 +719,8 @@ glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, temp_box.x1 = 0; if (temp_box.y1 < 0) temp_box.y1 = 0; - temp_box.x2 = MIN(temp_box.x2, priv->base.pixmap->drawable.width); - temp_box.y2 = MIN(temp_box.y2, priv->base.pixmap->drawable.height); + temp_box.x2 = MIN(temp_box.x2, pixmap->drawable.width); + temp_box.y2 = MIN(temp_box.y2, pixmap->drawable.height); } /* Now copy back the box32 to a box16 box. */ short_box.x1 = temp_box.x1; @@ -725,7 +730,8 @@ glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, RegionInitBoxes(temp_region, &short_box, 1); DEBUGF("copy to temp source region \n"); DEBUGRegionPrint(temp_region); - ret = _glamor_compute_clipped_regions(priv, + ret = _glamor_compute_clipped_regions(pixmap, + priv, temp_region, n_region, repeat_type, 1, reverse, upsidedown); @@ -747,12 +753,12 @@ glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, * if the clipped result cross the region boundary. */ static void -glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, +glamor_merge_clipped_regions(PixmapPtr pixmap, + glamor_pixmap_private *pixmap_priv, int repeat_type, glamor_pixmap_clipped_regions *clipped_regions, int *n_regions, int *need_clean_fbo) { - BoxPtr temp_extent; BoxRec temp_box, copy_box; RegionPtr temp_region; glamor_pixmap_private *temp_priv; @@ -760,11 +766,11 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, int overlap; int i; int pixmap_width, pixmap_height; - glamor_pixmap_private_large_t *priv; + glamor_pixmap_private *priv; priv = __glamor_large(pixmap_priv); - pixmap_width = priv->base.pixmap->drawable.width; - pixmap_height = priv->base.pixmap->drawable.height; + pixmap_width = pixmap->drawable.width; + pixmap_height =pixmap->drawable.height; temp_region = RegionCreate(NULL, 4); for (i = 0; i < *n_regions; i++) { @@ -776,18 +782,17 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, RegionValidate(temp_region, &overlap); DEBUGF("temp region: \n"); DEBUGRegionPrint(temp_region); - temp_extent = RegionExtents(temp_region); - temp_box = *temp_extent; + temp_box = *RegionExtents(temp_region); DEBUGF("need copy region: \n"); DEBUGF("%d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2, temp_box.y2); temp_pixmap = - glamor_create_pixmap(priv->base.pixmap->drawable.pScreen, + glamor_create_pixmap(pixmap->drawable.pScreen, temp_box.x2 - temp_box.x1, temp_box.y2 - temp_box.y1, - priv->base.pixmap->drawable.depth, + pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_FIXUP); if (temp_pixmap == NULL) { assert(0); @@ -795,20 +800,20 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, } temp_priv = glamor_get_pixmap_private(temp_pixmap); - assert(temp_priv->type != GLAMOR_TEXTURE_LARGE); + assert(glamor_pixmap_priv_is_small(temp_priv)); priv->box = temp_box; - if (temp_extent->x1 >= 0 && temp_extent->x2 <= pixmap_width - && temp_extent->y1 >= 0 && temp_extent->y2 <= pixmap_height) { + if (temp_box.x1 >= 0 && temp_box.x2 <= pixmap_width + && temp_box.y1 >= 0 && temp_box.y2 <= pixmap_height) { int dx, dy; copy_box.x1 = 0; copy_box.y1 = 0; - copy_box.x2 = temp_extent->x2 - temp_extent->x1; - copy_box.y2 = temp_extent->y2 - temp_extent->y1; - dx = temp_extent->x1; - dy = temp_extent->y1; - glamor_copy(&priv->base.pixmap->drawable, + copy_box.x2 = temp_box.x2 - temp_box.x1; + copy_box.y2 = temp_box.y2 - temp_box.y1; + dx = temp_box.x1; + dy = temp_box.y1; + glamor_copy(&pixmap->drawable, &temp_pixmap->drawable, NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); // glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, @@ -840,7 +845,7 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, copy_box.x1, copy_box.y1, copy_box.x2, copy_box.y2, dx, dy); - glamor_copy(&priv->base.pixmap->drawable, + glamor_copy(&pixmap->drawable, &temp_pixmap->drawable, NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); @@ -855,7 +860,7 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, RegionDestroy(clipped_regions[i].region); RegionDestroy(temp_region); priv->box = temp_box; - priv->base.fbo = glamor_pixmap_detach_fbo(temp_priv); + priv->fbo = glamor_pixmap_detach_fbo(temp_priv); DEBUGF("priv box x1 %d y1 %d x2 %d y2 %d \n", priv->box.x1, priv->box.y1, priv->box.x2, priv->box.y2); glamor_destroy_pixmap(temp_pixmap); @@ -875,7 +880,7 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, * boundary and can avoid some overhead. * **/ -Bool +static Bool glamor_get_transform_block_size(struct pixman_transform *transform, int block_w, int block_h, int *transformed_block_w, @@ -920,11 +925,11 @@ glamor_get_transform_block_size(struct pixman_transform *transform, return TRUE; } -#define VECTOR_FROM_POINT(p, x, y) \ +#define VECTOR_FROM_POINT(p, x, y) do {\ p.v[0] = x; \ p.v[1] = y; \ - p.v[2] = 1.0; -void + p.v[2] = 1.0; } while (0) +static void glamor_get_transform_extent_from_box(struct pixman_box32 *box, struct pixman_transform *transform) { @@ -933,12 +938,12 @@ glamor_get_transform_extent_from_box(struct pixman_box32 *box, struct pixman_f_transform ftransform; - VECTOR_FROM_POINT(p0, box->x1, box->y1) - VECTOR_FROM_POINT(p1, box->x2, box->y1) - VECTOR_FROM_POINT(p2, box->x2, box->y2) - VECTOR_FROM_POINT(p3, box->x1, box->y2) + VECTOR_FROM_POINT(p0, box->x1, box->y1); + VECTOR_FROM_POINT(p1, box->x2, box->y1); + VECTOR_FROM_POINT(p2, box->x2, box->y2); + VECTOR_FROM_POINT(p3, box->x1, box->y2); - pixman_f_transform_from_pixman_transform(&ftransform, transform); + pixman_f_transform_from_pixman_transform(&ftransform, transform); pixman_f_transform_point(&ftransform, &p0); pixman_f_transform_point(&ftransform, &p1); pixman_f_transform_point(&ftransform, &p2); @@ -966,7 +971,8 @@ glamor_get_transform_extent_from_box(struct pixman_box32 *box, } static void -_glamor_process_transformed_clipped_region(glamor_pixmap_private *priv, +_glamor_process_transformed_clipped_region(PixmapPtr pixmap, + glamor_pixmap_private *priv, int repeat_type, glamor_pixmap_clipped_regions * clipped_regions, int *n_regions, @@ -976,7 +982,7 @@ _glamor_process_transformed_clipped_region(glamor_pixmap_private *priv, if (*n_regions != 1) { /* Merge all source regions into one region. */ - glamor_merge_clipped_regions(priv, repeat_type, + glamor_merge_clipped_regions(pixmap, priv, repeat_type, clipped_regions, n_regions, need_clean_fbo); } @@ -990,22 +996,22 @@ _glamor_process_transformed_clipped_region(glamor_pixmap_private *priv, int rem; temp_box = RegionExtents(clipped_regions[0].region); - modulus(temp_box->x1, priv->base.pixmap->drawable.width, rem); - shift_x = (temp_box->x1 - rem) / priv->base.pixmap->drawable.width; - modulus(temp_box->y1, priv->base.pixmap->drawable.height, rem); - shift_y = (temp_box->y1 - rem) / priv->base.pixmap->drawable.height; + modulus(temp_box->x1, pixmap->drawable.width, rem); + shift_x = (temp_box->x1 - rem) / pixmap->drawable.width; + modulus(temp_box->y1, pixmap->drawable.height, rem); + shift_y = (temp_box->y1 - rem) / pixmap->drawable.height; if (shift_x != 0) { __glamor_large(priv)->box.x1 += - shift_x * priv->base.pixmap->drawable.width; + shift_x * pixmap->drawable.width; __glamor_large(priv)->box.x2 += - shift_x * priv->base.pixmap->drawable.width; + shift_x * pixmap->drawable.width; } if (shift_y != 0) { __glamor_large(priv)->box.y1 += - shift_y * priv->base.pixmap->drawable.height; + shift_y * pixmap->drawable.height; __glamor_large(priv)->box.y2 += - shift_y * priv->base.pixmap->drawable.height; + shift_y * pixmap->drawable.height; } } } @@ -1016,9 +1022,9 @@ glamor_composite_largepixmap_region(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, + PixmapPtr source_pixmap, + PixmapPtr mask_pixmap, + PixmapPtr dest_pixmap, RegionPtr region, Bool force_clip, INT16 x_source, INT16 y_source, @@ -1027,6 +1033,11 @@ glamor_composite_largepixmap_region(CARD8 op, INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) { + ScreenPtr screen = dest_pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_pixmap_private *source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + glamor_pixmap_private *mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + glamor_pixmap_private *dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); glamor_pixmap_clipped_regions *clipped_dest_regions; glamor_pixmap_clipped_regions *clipped_source_regions; glamor_pixmap_clipped_regions *clipped_mask_regions; @@ -1046,11 +1057,11 @@ glamor_composite_largepixmap_region(CARD8 op, int source_repeat_type = 0, mask_repeat_type = 0; int ok = TRUE; - if (source_pixmap_priv == dest_pixmap_priv) { + if (source_pixmap == dest_pixmap) { glamor_fallback("source and dest pixmaps are the same\n"); return FALSE; } - if (mask_pixmap_priv == dest_pixmap_priv) { + if (mask_pixmap == dest_pixmap) { glamor_fallback("mask and dest pixmaps are the same\n"); return FALSE; } @@ -1065,12 +1076,12 @@ glamor_composite_largepixmap_region(CARD8 op, else mask_repeat_type = RepeatNone; - if (dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (glamor_pixmap_priv_is_large(dest_pixmap_priv)) { dest_block_width = __glamor_large(dest_pixmap_priv)->block_w; dest_block_height = __glamor_large(dest_pixmap_priv)->block_h; } else { - dest_block_width = dest_pixmap_priv->base.pixmap->drawable.width; - dest_block_height = dest_pixmap_priv->base.pixmap->drawable.height; + dest_block_width = dest_pixmap->drawable.width; + dest_block_height = dest_pixmap->drawable.height; } fixed_block_width = dest_block_width; fixed_block_height = dest_block_height; @@ -1096,7 +1107,7 @@ glamor_composite_largepixmap_region(CARD8 op, */ if (source_pixmap_priv && source->transform - && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + && glamor_pixmap_priv_is_large(source_pixmap_priv)) { int source_transformed_block_width, source_transformed_block_height; if (!glamor_get_transform_block_size(source->transform, @@ -1118,7 +1129,7 @@ glamor_composite_largepixmap_region(CARD8 op, } if (mask_pixmap_priv - && mask->transform && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + && mask->transform && glamor_pixmap_priv_is_large(mask_pixmap_priv)) { int mask_transformed_block_width, mask_transformed_block_height; if (!glamor_get_transform_block_size(mask->transform, @@ -1143,12 +1154,12 @@ glamor_composite_largepixmap_region(CARD8 op, if (force_clip || fixed_block_width < dest_block_width || fixed_block_height < dest_block_height) clipped_dest_regions = - glamor_compute_clipped_regions_ext(dest_pixmap_priv, region, + glamor_compute_clipped_regions_ext(dest_pixmap, region, &n_dest_regions, fixed_block_width, fixed_block_height, 0, 0); else - clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv, + clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap, region, &n_dest_regions, 0, 0, 0); @@ -1156,7 +1167,7 @@ glamor_composite_largepixmap_region(CARD8 op, if (source_pixmap_priv && (source_pixmap_priv == dest_pixmap_priv || source_pixmap_priv == mask_pixmap_priv) - && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + && glamor_pixmap_priv_is_large(source_pixmap_priv)) { /* XXX self-copy... */ need_free_source_pixmap_priv = source_pixmap_priv; source_pixmap_priv = malloc(sizeof(*source_pixmap_priv)); @@ -1172,12 +1183,12 @@ glamor_composite_largepixmap_region(CARD8 op, glamor_set_pixmap_fbo_current(dest_pixmap_priv, clipped_dest_regions[i].block_idx); if (source_pixmap_priv && - source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + glamor_pixmap_priv_is_large(source_pixmap_priv)) { if (!source->transform && source_repeat_type != RepeatPad) { RegionTranslate(clipped_dest_regions[i].region, x_source - x_dest, y_source - y_dest); clipped_source_regions = - glamor_compute_clipped_regions(source_pixmap_priv, + glamor_compute_clipped_regions(source_pixmap, clipped_dest_regions[i]. region, &n_source_regions, source_repeat_type, 0, 0); @@ -1185,7 +1196,7 @@ glamor_composite_largepixmap_region(CARD8 op, } else { clipped_source_regions = - glamor_compute_transform_clipped_regions(source_pixmap_priv, + glamor_compute_transform_clipped_regions(source_pixmap, source->transform, clipped_dest_regions [i].region, @@ -1202,7 +1213,7 @@ glamor_composite_largepixmap_region(CARD8 op, } else _glamor_process_transformed_clipped_region - (source_pixmap_priv, source_repeat_type, + (source_pixmap, source_pixmap_priv, source_repeat_type, clipped_source_regions, &n_source_regions, &need_clean_source_fbo); } @@ -1213,7 +1224,7 @@ glamor_composite_largepixmap_region(CARD8 op, clipped_source_regions[j].block_idx); if (mask_pixmap_priv && - mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + glamor_pixmap_priv_is_large(mask_pixmap_priv)) { if (is_normal_mask_fbo && is_normal_source_fbo) { /* both mask and source are normal fbo box without transform or repeatpad. * The region is clipped against source and then we clip it against mask here.*/ @@ -1223,7 +1234,7 @@ glamor_composite_largepixmap_region(CARD8 op, RegionTranslate(clipped_source_regions[j].region, -x_source + x_mask, -y_source + y_mask); clipped_mask_regions = - glamor_compute_clipped_regions(mask_pixmap_priv, + glamor_compute_clipped_regions(mask_pixmap, clipped_source_regions [j].region, &n_mask_regions, @@ -1239,7 +1250,7 @@ glamor_composite_largepixmap_region(CARD8 op, RegionTranslate(clipped_dest_regions[i].region, -x_dest + x_mask, -y_dest + y_mask); clipped_mask_regions = - glamor_compute_clipped_regions(mask_pixmap_priv, + glamor_compute_clipped_regions(mask_pixmap, clipped_dest_regions [i].region, &n_mask_regions, @@ -1253,14 +1264,14 @@ glamor_composite_largepixmap_region(CARD8 op, if (!is_normal_source_fbo) clipped_mask_regions = glamor_compute_transform_clipped_regions - (mask_pixmap_priv, mask->transform, + (mask_pixmap, mask->transform, clipped_dest_regions[i].region, &n_mask_regions, x_mask - x_dest, y_mask - y_dest, mask_repeat_type, 0, 0); else clipped_mask_regions = glamor_compute_transform_clipped_regions - (mask_pixmap_priv, mask->transform, + (mask_pixmap, mask->transform, clipped_source_regions[j].region, &n_mask_regions, x_mask - x_source, y_mask - y_source, mask_repeat_type, 0, 0); @@ -1272,7 +1283,7 @@ glamor_composite_largepixmap_region(CARD8 op, } else _glamor_process_transformed_clipped_region - (mask_pixmap_priv, mask_repeat_type, + (mask_pixmap, mask_pixmap_priv, mask_repeat_type, clipped_mask_regions, &n_mask_regions, &need_clean_mask_fbo); } @@ -1282,9 +1293,9 @@ glamor_composite_largepixmap_region(CARD8 op, if (!glamor_composite_clipped_region(op, \ null_source ? NULL : source, \ null_mask ? NULL : mask, dest, \ - null_source ? NULL : source_pixmap_priv, \ - null_mask ? NULL : mask_pixmap_priv, \ - dest_pixmap_priv, region, \ + null_source ? NULL : source_pixmap, \ + null_mask ? NULL : mask_pixmap, \ + dest_pixmap, region, \ x_source, y_source, x_mask, y_mask, \ x_dest, y_dest)) { \ assert(0); \ @@ -1335,8 +1346,8 @@ glamor_composite_largepixmap_region(CARD8 op, null_mask = 0; if (need_clean_mask_fbo) { assert(is_normal_mask_fbo == 0); - glamor_destroy_fbo(mask_pixmap_priv->base.fbo); - mask_pixmap_priv->base.fbo = NULL; + glamor_destroy_fbo(glamor_priv, mask_pixmap_priv->fbo); + mask_pixmap_priv->fbo = NULL; need_clean_mask_fbo = 0; } } @@ -1364,19 +1375,19 @@ glamor_composite_largepixmap_region(CARD8 op, null_source = 0; if (need_clean_source_fbo) { assert(is_normal_source_fbo == 0); - glamor_destroy_fbo(source_pixmap_priv->base.fbo); - source_pixmap_priv->base.fbo = NULL; + glamor_destroy_fbo(glamor_priv, source_pixmap_priv->fbo); + source_pixmap_priv->fbo = NULL; need_clean_source_fbo = 0; } } else { if (mask_pixmap_priv && - mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + glamor_pixmap_priv_is_large(mask_pixmap_priv)) { if (!mask->transform && mask_repeat_type != RepeatPad) { RegionTranslate(clipped_dest_regions[i].region, x_mask - x_dest, y_mask - y_dest); clipped_mask_regions = - glamor_compute_clipped_regions(mask_pixmap_priv, + glamor_compute_clipped_regions(mask_pixmap, clipped_dest_regions[i]. region, &n_mask_regions, mask_repeat_type, 0, 0); @@ -1385,7 +1396,7 @@ glamor_composite_largepixmap_region(CARD8 op, else { clipped_mask_regions = glamor_compute_transform_clipped_regions - (mask_pixmap_priv, mask->transform, + (mask_pixmap, mask->transform, clipped_dest_regions[i].region, &n_mask_regions, x_mask - x_dest, y_mask - y_dest, mask_repeat_type, 0, 0); @@ -1397,7 +1408,7 @@ glamor_composite_largepixmap_region(CARD8 op, } else _glamor_process_transformed_clipped_region - (mask_pixmap_priv, mask_repeat_type, + (mask_pixmap, mask_pixmap_priv, mask_repeat_type, clipped_mask_regions, &n_mask_regions, &need_clean_mask_fbo); } @@ -1426,8 +1437,8 @@ glamor_composite_largepixmap_region(CARD8 op, if (null_mask) null_mask = 0; if (need_clean_mask_fbo) { - glamor_destroy_fbo(mask_pixmap_priv->base.fbo); - mask_pixmap_priv->base.fbo = NULL; + glamor_destroy_fbo(glamor_priv, mask_pixmap_priv->fbo); + mask_pixmap_priv->fbo = NULL; need_clean_mask_fbo = 0; } } diff --git a/xserver/glamor/glamor_lines.c b/xserver/glamor/glamor_lines.c index e9a619505..a2c9b1fcc 100644 --- a/xserver/glamor/glamor_lines.c +++ b/xserver/glamor/glamor_lines.c @@ -44,7 +44,7 @@ glamor_poly_lines_solid_gl(DrawablePtr drawable, GCPtr gc, int off_x, off_y; DDXPointPtr v; char *vbo_offset; - int box_x, box_y; + int box_index; int add_last; pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -65,7 +65,7 @@ glamor_poly_lines_solid_gl(DrawablePtr drawable, GCPtr gc, &glamor_facet_poly_lines); if (!prog) - goto bail_ctx; + goto bail; /* Set up the vertex buffers for the points */ @@ -99,11 +99,11 @@ glamor_poly_lines_solid_gl(DrawablePtr drawable, GCPtr gc, glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); - glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE, + glamor_set_destination_drawable(drawable, box_index, TRUE, TRUE, prog->matrix_uniform, &off_x, &off_y); while (nbox--) { @@ -117,12 +117,9 @@ glamor_poly_lines_solid_gl(DrawablePtr drawable, GCPtr gc, } glDisable(GL_SCISSOR_TEST); - glDisable(GL_COLOR_LOGIC_OP); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); return TRUE; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } @@ -167,21 +164,3 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, return; glamor_poly_lines_bail(drawable, gc, mode, n, points); } - -Bool -glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, - int mode, int n, DDXPointPtr points) -{ - if (glamor_poly_lines_gl(drawable, gc, mode, n, points)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable) && - glamor_ddx_fallback_check_gc(gc)) - { - return FALSE; - } - - glamor_poly_lines_bail(drawable, gc, mode, n, points); - return TRUE; -} - diff --git a/xserver/glamor/glamor_picture.c b/xserver/glamor/glamor_picture.c index bc658f801..b069ce56b 100644 --- a/xserver/glamor/glamor_picture.c +++ b/xserver/glamor/glamor_picture.c @@ -31,83 +31,904 @@ #include "glamor_priv.h" #include "mipict.h" -/* Upload picture to texture. We may need to flip the y axis or - * wire alpha to 1. So we may conditional create fbo for the picture. - * */ -enum glamor_pixmap_status -glamor_upload_picture_to_texture(PicturePtr picture) +/* + * Map picture's format to the correct gl texture format and type. + * no_alpha is used to indicate whehter we need to wire alpha to 1. + * + * Although opengl support A1/GL_BITMAP, we still don't use it + * here, it seems that mesa has bugs when uploading a A1 bitmap. + * + * Return 0 if find a matched texture type. Otherwise return -1. + **/ +static int +glamor_get_tex_format_type_from_pictformat_gl(ScreenPtr pScreen, + PictFormatShort format, + GLenum *tex_format, + GLenum *tex_type, + int *no_alpha, + int *revert, + int *swap_rb, int is_upload) { - PixmapPtr pixmap; + glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); + *no_alpha = 0; + *revert = REVERT_NONE; + *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING; + switch (format) { + case PICT_a1: + *tex_format = glamor_priv->one_channel_format; + *tex_type = GL_UNSIGNED_BYTE; + *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1; + break; + case PICT_b8g8r8x8: + *no_alpha = 1; + case PICT_b8g8r8a8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8; + break; - assert(picture->pDrawable); - pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + case PICT_x8r8g8b8: + *no_alpha = 1; + case PICT_a8r8g8b8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x8b8g8r8: + *no_alpha = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x2r10g10b10: + *no_alpha = 1; + case PICT_a2r10g10b10: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + case PICT_x2b10g10r10: + *no_alpha = 1; + case PICT_a2b10g10r10: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + + case PICT_r5g6b5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + break; + case PICT_b5g6r5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV; + break; + case PICT_x1b5g5r5: + *no_alpha = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + + case PICT_x1r5g5b5: + *no_alpha = 1; + case PICT_a1r5g5b5: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + case PICT_a8: + *tex_format = glamor_priv->one_channel_format; + *tex_type = GL_UNSIGNED_BYTE; + break; + case PICT_x4r4g4b4: + *no_alpha = 1; + case PICT_a4r4g4b4: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + break; + + case PICT_x4b4g4r4: + *no_alpha = 1; + case PICT_a4b4g4r4: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + break; + + default: + return -1; + } + return 0; +} + +#define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) + +static int +glamor_get_tex_format_type_from_pictformat_gles2(ScreenPtr pScreen, + PictFormatShort format, + GLenum *tex_format, + GLenum *tex_type, + int *no_alpha, + int *revert, + int *swap_rb, int is_upload) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); + int need_swap_rb = 0; + + *no_alpha = 0; + *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL; + + switch (format) { + case PICT_b8g8r8x8: + *no_alpha = 1; + case PICT_b8g8r8a8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_BYTE; + need_swap_rb = 1; + *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; + break; + + case PICT_x8r8g8b8: + *no_alpha = 1; + case PICT_a8r8g8b8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_BYTE; + need_swap_rb = 1; + break; + + case PICT_x8b8g8r8: + *no_alpha = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_BYTE; + break; + + case PICT_x2r10g10b10: + *no_alpha = 1; + case PICT_a2r10g10b10: + *tex_format = GL_RGBA; + /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2. + * we have to use GL_UNSIGNED_BYTE and do the conversion in + * shader latter.*/ + *tex_type = GL_UNSIGNED_BYTE; + if (is_upload == 1) { + if (!IS_LITTLE_ENDIAN) + *revert = REVERT_UPLOADING_10_10_10_2; + else + *revert = REVERT_UPLOADING_2_10_10_10; + } + else { + if (!IS_LITTLE_ENDIAN) { + *revert = REVERT_DOWNLOADING_10_10_10_2; + } + else { + *revert = REVERT_DOWNLOADING_2_10_10_10; + } + } + need_swap_rb = 1; + + break; + + case PICT_x2b10g10r10: + *no_alpha = 1; + case PICT_a2b10g10r10: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_BYTE; + if (is_upload == 1) { + if (!IS_LITTLE_ENDIAN) + *revert = REVERT_UPLOADING_10_10_10_2; + else + *revert = REVERT_UPLOADING_2_10_10_10; + } + else { + if (!IS_LITTLE_ENDIAN) { + *revert = REVERT_DOWNLOADING_10_10_10_2; + } + else { + *revert = REVERT_DOWNLOADING_2_10_10_10; + } + } + break; + + case PICT_r5g6b5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL; + + break; + + case PICT_b5g6r5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0; + break; + + case PICT_x1b5g5r5: + *no_alpha = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_5_5_5_1; + if (IS_LITTLE_ENDIAN) { + *revert = + is_upload ? REVERT_UPLOADING_1_5_5_5 : + REVERT_DOWNLOADING_1_5_5_5; + } + else + *revert = REVERT_NONE; + break; + + case PICT_x1r5g5b5: + *no_alpha = 1; + case PICT_a1r5g5b5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_5_5_5_1; + if (IS_LITTLE_ENDIAN) { + *revert = + is_upload ? REVERT_UPLOADING_1_5_5_5 : + REVERT_DOWNLOADING_1_5_5_5; + } + else + *revert = REVERT_NONE; + need_swap_rb = 1; + break; + + case PICT_a1: + *tex_format = glamor_priv->one_channel_format; + *tex_type = GL_UNSIGNED_BYTE; + *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1; + break; + + case PICT_a8: + *tex_format = glamor_priv->one_channel_format; + *tex_type = GL_UNSIGNED_BYTE; + *revert = REVERT_NONE; + break; + + case PICT_x4r4g4b4: + *no_alpha = 1; + case PICT_a4r4g4b4: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; + *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; + need_swap_rb = 1; + break; + + case PICT_x4b4g4r4: + *no_alpha = 1; + case PICT_a4b4g4r4: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; + *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; + break; + + default: + LogMessageVerb(X_INFO, 0, + "fail to get matched format for %x \n", format); + return -1; + } - return glamor_upload_pixmap_to_texture(pixmap); + if (need_swap_rb) + *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING; + else + *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING; + return 0; +} + +static int +glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, + PictFormatShort pict_format, + GLenum *format, + GLenum *type, + int *no_alpha, + int *revert, int *swap_rb, int is_upload) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + return glamor_get_tex_format_type_from_pictformat_gl(pixmap->drawable.pScreen, + pict_format, + format, type, + no_alpha, + revert, + swap_rb, + is_upload); + } else { + return glamor_get_tex_format_type_from_pictformat_gles2(pixmap->drawable.pScreen, + pict_format, + format, type, + no_alpha, + revert, + swap_rb, + is_upload); + } +} + +static void * +_glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, + int stride, int revert) +{ + PictFormatShort dst_format, src_format; + pixman_image_t *dst_image; + pixman_image_t *src_image; + int src_stride; + + if (revert == REVERT_UPLOADING_A1) { + src_format = PICT_a1; + dst_format = PICT_a8; + src_stride = PixmapBytePad(w, 1); + } + else { + dst_format = PICT_a1; + src_format = PICT_a8; + src_stride = (((w * 8 + 7) / 8) + 3) & ~3; + } + + dst_image = pixman_image_create_bits(dst_format, w, h, dst_bits, stride); + if (dst_image == NULL) { + return NULL; + } + + src_image = pixman_image_create_bits(src_format, + w, h, src_bits, src_stride); + + if (src_image == NULL) { + pixman_image_unref(dst_image); + return NULL; + } + + pixman_image_composite(PictOpSrc, src_image, NULL, dst_image, + 0, 0, 0, 0, 0, 0, w, h); + + pixman_image_unref(src_image); + pixman_image_unref(dst_image); + return dst_bits; +} + +#define ADJUST_BITS(d, src_bits, dst_bits) (((dst_bits) == (src_bits)) ? (d) : \ + (((dst_bits) > (src_bits)) ? \ + (((d) << ((dst_bits) - (src_bits))) \ + + (( 1 << ((dst_bits) - (src_bits))) >> 1)) \ + : ((d) >> ((src_bits) - (dst_bits))))) + +#define GLAMOR_DO_CONVERT(src, dst, no_alpha, swap, \ + a_shift_src, a_bits_src, \ + b_shift_src, b_bits_src, \ + g_shift_src, g_bits_src, \ + r_shift_src, r_bits_src, \ + a_shift, a_bits, \ + b_shift, b_bits, \ + g_shift, g_bits, \ + r_shift, r_bits) \ + do { \ + typeof(src) a,b,g,r; \ + typeof(src) a_mask_src, b_mask_src, g_mask_src, r_mask_src;\ + a_mask_src = (((1 << (a_bits_src)) - 1) << a_shift_src);\ + b_mask_src = (((1 << (b_bits_src)) - 1) << b_shift_src);\ + g_mask_src = (((1 << (g_bits_src)) - 1) << g_shift_src);\ + r_mask_src = (((1 << (r_bits_src)) - 1) << r_shift_src);\ + if (no_alpha) \ + a = (a_mask_src) >> (a_shift_src); \ + else \ + a = ((src) & (a_mask_src)) >> (a_shift_src); \ + b = ((src) & (b_mask_src)) >> (b_shift_src); \ + g = ((src) & (g_mask_src)) >> (g_shift_src); \ + r = ((src) & (r_mask_src)) >> (r_shift_src); \ + a = ADJUST_BITS(a, a_bits_src, a_bits); \ + b = ADJUST_BITS(b, b_bits_src, b_bits); \ + g = ADJUST_BITS(g, g_bits_src, g_bits); \ + r = ADJUST_BITS(r, r_bits_src, r_bits); \ + if (swap == 0) \ + (*dst) = ((a) << (a_shift)) | ((b) << (b_shift)) | ((g) << (g_shift)) | ((r) << (r_shift)); \ + else \ + (*dst) = ((a) << (a_shift)) | ((r) << (b_shift)) | ((g) << (g_shift)) | ((b) << (r_shift)); \ + } while (0) + +static void * +_glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h, + int stride, int no_alpha, int revert, + int swap_rb) +{ + int x, y; + unsigned int *words, *saved_words, *source_words; + int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || + swap_rb == SWAP_NONE_UPLOADING); + + source_words = src_bits; + words = dst_bits; + saved_words = words; + + for (y = 0; y < h; y++) { + DEBUGF("Line %d : ", y); + for (x = 0; x < w; x++) { + unsigned int pixel = source_words[x]; + + if (revert == REVERT_DOWNLOADING_2_10_10_10) + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 24, 8, 16, 8, 8, 8, 0, 8, + 30, 2, 20, 10, 10, 10, 0, 10); + else + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 30, 2, 20, 10, 10, 10, 0, 10, + 24, 8, 16, 8, 8, 8, 0, 8); + DEBUGF("%x:%x ", pixel, words[x]); + } + DEBUGF("\n"); + words += stride / sizeof(*words); + source_words += stride / sizeof(*words); + } + DEBUGF("\n"); + return saved_words; + +} + +static void * +_glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h, + int stride, int no_alpha, int revert, int swap_rb) +{ + int x, y; + unsigned short *words, *saved_words, *source_words; + int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || + swap_rb == SWAP_NONE_UPLOADING); + + words = dst_bits; + source_words = src_bits; + saved_words = words; + + for (y = 0; y < h; y++) { + DEBUGF("Line %d : ", y); + for (x = 0; x < w; x++) { + unsigned short pixel = source_words[x]; + + if (revert == REVERT_DOWNLOADING_1_5_5_5) + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 0, 1, 1, 5, 6, 5, 11, 5, + 15, 1, 10, 5, 5, 5, 0, 5); + else + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 15, 1, 10, 5, 5, 5, 0, 5, + 0, 1, 1, 5, 6, 5, 11, 5); + DEBUGF("%04x:%04x ", pixel, words[x]); + } + DEBUGF("\n"); + words += stride / sizeof(*words); + source_words += stride / sizeof(*words); + } + DEBUGF("\n"); + return saved_words; } /* - * We should already have drawable attached to it, if it has one. - * Then set the attached pixmap to is_picture format, and set - * the pict format. - * */ -int -glamor_create_picture(PicturePtr picture) + * This function is to convert an unsupported color format to/from a + * supported GL format. + * Here are the current scenarios: + * + * @no_alpha: + * If it is set, then we need to wire the alpha value to 1. + * @revert: + REVERT_DOWNLOADING_A1 : convert an Alpha8 buffer to a A1 buffer. + REVERT_UPLOADING_A1 : convert an A1 buffer to an Alpha8 buffer + REVERT_DOWNLOADING_2_10_10_10 : convert r10G10b10X2 to X2B10G10R10 + REVERT_UPLOADING_2_10_10_10 : convert X2B10G10R10 to R10G10B10X2 + REVERT_DOWNLOADING_1_5_5_5 : convert B5G5R5X1 to X1R5G5B5 + REVERT_UPLOADING_1_5_5_5 : convert X1R5G5B5 to B5G5R5X1 + @swap_rb: if we have the swap_rb set, then we need to swap the R and B's position. + * + */ + +static void * +glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, + int stride, int no_alpha, int revert, int swap_rb) { - PixmapPtr pixmap; + if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) { + return _glamor_color_convert_a1_a8(src_bits, dst_bits, w, h, stride, + revert); + } + else if (revert == REVERT_DOWNLOADING_2_10_10_10 || + revert == REVERT_UPLOADING_2_10_10_10) { + return _glamor_color_revert_x2b10g10r10(src_bits, dst_bits, w, h, + stride, no_alpha, revert, + swap_rb); + } + else if (revert == REVERT_DOWNLOADING_1_5_5_5 || + revert == REVERT_UPLOADING_1_5_5_5) { + return _glamor_color_revert_x1b5g5r5(src_bits, dst_bits, w, h, stride, + no_alpha, revert, swap_rb); + } + else + ErrorF("convert a non-supported mode %x.\n", revert); + + return NULL; +} + +/** + * Upload pixmap to a specified texture. + * This texture may not be the one attached to it. + **/ +static Bool +__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, + GLenum format, + GLenum type, + int x, int y, int w, int h, + void *bits, int pbo) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + int non_sub = 0; + unsigned int iformat = 0; + + glamor_make_current(glamor_priv); + if (*tex == 0) { + glGenTextures(1, tex); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + iformat = gl_iformat_for_pixmap(pixmap); + else + iformat = format; + non_sub = 1; + assert(x == 0 && y == 0); + } + + 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); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + assert(pbo || bits != 0); + if (bits == NULL) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + } + glamor_priv->suppress_gl_out_of_memory_logging = true; + if (non_sub) + glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits); + else + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits); + glamor_priv->suppress_gl_out_of_memory_logging = false; + if (glGetError() == GL_OUT_OF_MEMORY) { + if (non_sub) { + glDeleteTextures(1, tex); + *tex = 0; + } + return FALSE; + } + + if (bits == NULL) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + return TRUE; +} + +static Bool +_glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, + GLenum type, int no_alpha, int revert, + int swap_rb, int x, int y, int w, int h, + int stride, void *bits, int pbo) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + float dst_xscale, dst_yscale; + GLuint tex = 0; + int need_free_bits = 0; + + if (bits == NULL) + goto ready_to_upload; + + if (revert > REVERT_NORMAL) { + /* XXX if we are restoring the pixmap, then we may not need to allocate + * new buffer */ + void *converted_bits; + + if (pixmap->drawable.depth == 1) + stride = (((w * 8 + 7) / 8) + 3) & ~3; + + converted_bits = xallocarray(h, stride); + + if (converted_bits == NULL) + return FALSE; + bits = glamor_color_convert_to_bits(bits, converted_bits, w, h, + stride, no_alpha, revert, swap_rb); + if (bits == NULL) { + free(converted_bits); + ErrorF("Failed to convert pixmap no_alpha %d," + "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb); + return FALSE; + } + no_alpha = 0; + revert = REVERT_NONE; + swap_rb = SWAP_NONE_UPLOADING; + need_free_bits = TRUE; + } + + ready_to_upload: + + /* Try fast path firstly, upload the pixmap to the texture attached + * to the fbo directly. */ + if (no_alpha == 0 + && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING +#ifdef WALKAROUND_LARGE_TEXTURE_MAP + && glamor_pixmap_priv_is_small(pixmap_priv) +#endif + ) { + int fbo_x_off, fbo_y_off; + + assert(pixmap_priv->fbo->tex); + pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); + + assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0); + assert(x + fbo_x_off + w <= pixmap_priv->fbo->width); + assert(y + fbo_y_off + h <= pixmap_priv->fbo->height); + if (!__glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex, + format, type, + x + fbo_x_off, y + fbo_y_off, + w, h, + bits, pbo)) { + if (need_free_bits) + free(bits); + return FALSE; + } + } else { + static const float texcoords_inv[8] = { 0, 0, + 1, 0, + 1, 1, + 0, 1 + }; + GLfloat *v; + char *vbo_offset; + + v = glamor_get_vbo_space(screen, 16 * sizeof(GLfloat), &vbo_offset); + + pixmap_priv_get_dest_scale(pixmap, pixmap_priv, &dst_xscale, &dst_yscale); + glamor_set_normalize_vcoords(pixmap_priv, dst_xscale, + dst_yscale, + x, y, + x + w, y + h, + v); + /* Slow path, we need to flip y or wire alpha to 1. */ + glamor_make_current(glamor_priv); + + if (!__glamor_upload_pixmap_to_texture(pixmap, &tex, + format, type, 0, 0, w, h, bits, + pbo)) { + if (need_free_bits) + free(bits); + return FALSE; + } + + memcpy(&v[8], texcoords_inv, 8 * sizeof(GLfloat)); + + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), vbo_offset); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), vbo_offset + 8 * sizeof(GLfloat)); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + glamor_put_vbo_space(screen); + glamor_set_destination_pixmap_priv_nc(glamor_priv, pixmap, pixmap_priv); + glamor_set_alu(screen, GXcopy); + glActiveTexture(GL_TEXTURE0); + 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); + glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert); + glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glDeleteTextures(1, &tex); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + if (need_free_bits) + free(bits); + return TRUE; +} + +/* + * Prepare to upload a pixmap to texture memory. + * no_alpha equals 1 means the format needs to wire alpha to 1. + */ +static int +glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, + int revert, int swap_rb) +{ + int flag = 0; glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv; + glamor_pixmap_fbo *fbo; + GLenum iformat; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - if (!picture || !picture->pDrawable) + if (pixmap_priv->gl_fbo != GLAMOR_FBO_UNATTACHED) return 0; - pixmap = glamor_get_drawable_pixmap(picture->pDrawable); - pixmap_priv = glamor_get_pixmap_private(pixmap); - if (!pixmap_priv) { - /* We must create a pixmap priv to track the picture format even - * if the pixmap is a pure in memory pixmap. The reason is that - * we may need to upload this pixmap to a texture on the fly. During - * the uploading, we need to know the picture format. */ - glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); - pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv->fbo + && (pixmap_priv->fbo->width < pixmap->drawable.width + || pixmap_priv->fbo->height < pixmap->drawable.height)) { + fbo = glamor_pixmap_detach_fbo(pixmap_priv); + glamor_destroy_fbo(glamor_priv, fbo); } - else { - if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - /* If the picture format is not compatible with glamor fbo format, - * we have to mark this pixmap as a separated texture, and don't - * fallback to DDX layer. */ - if (pixmap_priv->type == GLAMOR_TEXTURE_DRM - && !glamor_pict_format_is_compatible(picture)) - glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE); - } + + if (pixmap_priv->fbo && pixmap_priv->fbo->fb) + return 0; + + if (!(no_alpha || (revert == REVERT_NORMAL) + || (swap_rb != SWAP_NONE_UPLOADING))) { + /* We don't need a fbo, a simple texture uploading should work. */ + + flag = GLAMOR_CREATE_FBO_NO_FBO; } - pixmap_priv->base.is_picture = 1; - pixmap_priv->base.picture = picture; + if ((flag == GLAMOR_CREATE_FBO_NO_FBO + && pixmap_priv->fbo && pixmap_priv->fbo->tex)) + return 0; + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + iformat = gl_iformat_for_pixmap(pixmap); + else + iformat = format; + + if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag)) + return -1; - return miCreatePicture(picture); + return 0; } -void -glamor_destroy_picture(PicturePtr picture) +/* + * upload sub region to a large region. + * */ +static void +glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits, + int src_stride, int bpp, int x, int y, int w, int h) { - PixmapPtr pixmap; + int j; + int byte_per_pixel; + + byte_per_pixel = bpp / 8; + src_bits += y * src_stride + (x * byte_per_pixel); + + for (j = y; j < y + h; j++) { + memcpy(dst_bits, src_bits, w * byte_per_pixel); + src_bits += src_stride; + dst_bits += dst_stride; + } +} + +static Bool +glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, + int h, int stride, void *bits, int pbo, + PictFormatShort pict_format) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + GLenum format, type; + int no_alpha, revert, swap_rb; glamor_pixmap_private *pixmap_priv; + Bool force_clip; - if (!picture || !picture->pDrawable) - return; + if (glamor_get_tex_format_type_from_pixmap(pixmap, + pict_format, + &format, + &type, + &no_alpha, + &revert, &swap_rb, 1)) { + glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); + return FALSE; + } + if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) + return FALSE; - pixmap = glamor_get_drawable_pixmap(picture->pDrawable); pixmap_priv = glamor_get_pixmap_private(pixmap); + force_clip = glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP + && !glamor_check_fbo_size(glamor_priv, w, h); + + if (glamor_pixmap_priv_is_large(pixmap_priv) || force_clip) { + RegionRec region; + BoxRec box; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + void *sub_bits; + int i, j; + + sub_bits = xallocarray(h, stride); + if (sub_bits == NULL) + return FALSE; + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + RegionInitBoxes(®ion, &box, 1); + if (!force_clip) + clipped_regions = + glamor_compute_clipped_regions(pixmap, ®ion, &n_region, + 0, 0, 0); + else + clipped_regions = + glamor_compute_clipped_regions_ext(pixmap, ®ion, + &n_region, + pixmap_priv->block_w, + pixmap_priv->block_h, + 0, + 0); + DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap); + for (i = 0; i < n_region; i++) { + BoxPtr boxes; + int nbox; + int temp_stride; + void *temp_bits; + + assert(pbo == 0); + + glamor_set_pixmap_fbo_current(pixmap_priv, clipped_regions[i].block_idx); + + boxes = RegionRects(clipped_regions[i].region); + nbox = RegionNumRects(clipped_regions[i].region); + DEBUGF("split to %d boxes\n", nbox); + for (j = 0; j < nbox; j++) { + temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1, + pixmap->drawable.depth); - if (pixmap_priv) { - pixmap_priv->base.is_picture = 0; - pixmap_priv->base.picture = NULL; + if (boxes[j].x1 == x && temp_stride == stride) { + temp_bits = (char *) bits + (boxes[j].y1 - y) * stride; + } + else { + temp_bits = sub_bits; + glamor_put_bits(temp_bits, temp_stride, bits, stride, + pixmap->drawable.bitsPerPixel, + boxes[j].x1 - x, boxes[j].y1 - y, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1); + } + DEBUGF("upload x %d y %d w %d h %d temp stride %d \n", + boxes[j].x1 - x, boxes[j].y1 - y, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1, temp_stride); + if (_glamor_upload_bits_to_pixmap_texture + (pixmap, format, type, no_alpha, revert, swap_rb, + boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits, + pbo) == FALSE) { + RegionUninit(®ion); + free(sub_bits); + assert(0); + return FALSE; + } + } + RegionDestroy(clipped_regions[i].region); + } + free(sub_bits); + free(clipped_regions); + RegionUninit(®ion); + return TRUE; } - miDestroyPicture(picture); + else + return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, + no_alpha, revert, swap_rb, + x, y, w, h, stride, bits, + pbo); } -void -glamor_picture_format_fixup(PicturePtr picture, - glamor_pixmap_private *pixmap_priv) +/* Upload picture to texture. We may need to flip the y axis or + * wire alpha to 1. So we may conditional create fbo for the picture. + * */ +enum glamor_pixmap_status +glamor_upload_picture_to_texture(PicturePtr picture) { - pixmap_priv->base.picture = picture; + PixmapPtr pixmap; + + assert(picture->pDrawable); + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + + if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->devKind, + pixmap->devPrivate.ptr, 0, + picture->format)) + return GLAMOR_UPLOAD_DONE; + else + return GLAMOR_UPLOAD_FAILED; } diff --git a/xserver/glamor/glamor_pixmap.c b/xserver/glamor/glamor_pixmap.c index 0d92710cf..166bde509 100644 --- a/xserver/glamor/glamor_pixmap.c +++ b/xserver/glamor/glamor_pixmap.c @@ -63,31 +63,36 @@ glamor_pixmap_fini(ScreenPtr screen) } void -glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *fbo, int x0, int y0, +glamor_set_destination_pixmap_fbo(glamor_screen_private *glamor_priv, + glamor_pixmap_fbo *fbo, int x0, int y0, int width, int height) { - glamor_make_current(fbo->glamor_priv); + glamor_make_current(glamor_priv); glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); glViewport(x0, y0, width, height); } void -glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) +glamor_set_destination_pixmap_priv_nc(glamor_screen_private *glamor_priv, + PixmapPtr pixmap, + glamor_pixmap_private *pixmap_priv) { int w, h; - PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap_priv, w, h); - glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0, w, h); + PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap, pixmap_priv, w, h); + glamor_set_destination_pixmap_fbo(glamor_priv, pixmap_priv->fbo, 0, 0, w, h); } int -glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv) +glamor_set_destination_pixmap_priv(glamor_screen_private *glamor_priv, + PixmapPtr pixmap, + glamor_pixmap_private *pixmap_priv) { if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return -1; - glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_set_destination_pixmap_priv_nc(glamor_priv, pixmap, pixmap_priv); return 0; } @@ -96,15 +101,17 @@ glamor_set_destination_pixmap(PixmapPtr pixmap) { int err; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - err = glamor_set_destination_pixmap_priv(pixmap_priv); + err = glamor_set_destination_pixmap_priv(glamor_priv, pixmap, pixmap_priv); return err; } Bool -glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask) +glamor_set_planemask(int depth, unsigned long planemask) { - if (glamor_pm_is_solid(&pixmap->drawable, planemask)) { + if (glamor_pm_is_solid(depth, planemask)) { return GL_TRUE; } @@ -182,1012 +189,3 @@ glamor_set_alu(ScreenPtr screen, unsigned char alu) return TRUE; } - -/* - * Map picture's format to the correct gl texture format and type. - * no_alpha is used to indicate whehter we need to wire alpha to 1. - * - * Although opengl support A1/GL_BITMAP, we still don't use it - * here, it seems that mesa has bugs when uploading a A1 bitmap. - * - * Return 0 if find a matched texture type. Otherwise return -1. - **/ -static int -glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format, - GLenum *tex_format, - GLenum *tex_type, - int *no_alpha, - int *revert, - int *swap_rb, int is_upload) -{ - *no_alpha = 0; - *revert = REVERT_NONE; - *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING; - switch (format) { - case PICT_a1: - *tex_format = GL_ALPHA; - *tex_type = GL_UNSIGNED_BYTE; - *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1; - break; - case PICT_b8g8r8x8: - *no_alpha = 1; - case PICT_b8g8r8a8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8; - break; - - case PICT_x8r8g8b8: - *no_alpha = 1; - case PICT_a8r8g8b8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case PICT_x8b8g8r8: - *no_alpha = 1; - case PICT_a8b8g8r8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case PICT_x2r10g10b10: - *no_alpha = 1; - case PICT_a2r10g10b10: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; - break; - case PICT_x2b10g10r10: - *no_alpha = 1; - case PICT_a2b10g10r10: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; - break; - - case PICT_r5g6b5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5; - break; - case PICT_b5g6r5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV; - break; - case PICT_x1b5g5r5: - *no_alpha = 1; - case PICT_a1b5g5r5: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - - case PICT_x1r5g5b5: - *no_alpha = 1; - case PICT_a1r5g5b5: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - case PICT_a8: - *tex_format = GL_ALPHA; - *tex_type = GL_UNSIGNED_BYTE; - break; - case PICT_x4r4g4b4: - *no_alpha = 1; - case PICT_a4r4g4b4: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - break; - - case PICT_x4b4g4r4: - *no_alpha = 1; - case PICT_a4b4g4r4: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - break; - - default: - return -1; - } - return 0; -} - -#define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) - -static int -glamor_get_tex_format_type_from_pictformat_gles2(PictFormatShort format, - GLenum *tex_format, - GLenum *tex_type, - int *no_alpha, - int *revert, - int *swap_rb, int is_upload) -{ - int need_swap_rb = 0; - - *no_alpha = 0; - *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL; - - switch (format) { - case PICT_b8g8r8x8: - *no_alpha = 1; - case PICT_b8g8r8a8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_BYTE; - need_swap_rb = 1; - *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; - break; - - case PICT_x8r8g8b8: - *no_alpha = 1; - case PICT_a8r8g8b8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_BYTE; - need_swap_rb = 1; - break; - - case PICT_x8b8g8r8: - *no_alpha = 1; - case PICT_a8b8g8r8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_BYTE; - break; - - case PICT_x2r10g10b10: - *no_alpha = 1; - case PICT_a2r10g10b10: - *tex_format = GL_RGBA; - /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2. - * we have to use GL_UNSIGNED_BYTE and do the conversion in - * shader latter.*/ - *tex_type = GL_UNSIGNED_BYTE; - if (is_upload == 1) { - if (!IS_LITTLE_ENDIAN) - *revert = REVERT_UPLOADING_10_10_10_2; - else - *revert = REVERT_UPLOADING_2_10_10_10; - } - else { - if (!IS_LITTLE_ENDIAN) { - *revert = REVERT_DOWNLOADING_10_10_10_2; - } - else { - *revert = REVERT_DOWNLOADING_2_10_10_10; - } - } - need_swap_rb = 1; - - break; - - case PICT_x2b10g10r10: - *no_alpha = 1; - case PICT_a2b10g10r10: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_BYTE; - if (is_upload == 1) { - if (!IS_LITTLE_ENDIAN) - *revert = REVERT_UPLOADING_10_10_10_2; - else - *revert = REVERT_UPLOADING_2_10_10_10; - } - else { - if (!IS_LITTLE_ENDIAN) { - *revert = REVERT_DOWNLOADING_10_10_10_2; - } - else { - *revert = REVERT_DOWNLOADING_2_10_10_10; - } - } - break; - - case PICT_r5g6b5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5; - *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL; - - break; - - case PICT_b5g6r5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5; - need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;; - break; - - case PICT_x1b5g5r5: - *no_alpha = 1; - case PICT_a1b5g5r5: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_5_5_5_1; - if (IS_LITTLE_ENDIAN) { - *revert = - is_upload ? REVERT_UPLOADING_1_5_5_5 : - REVERT_DOWNLOADING_1_5_5_5; - } - else - *revert = REVERT_NONE; - break; - - case PICT_x1r5g5b5: - *no_alpha = 1; - case PICT_a1r5g5b5: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_5_5_5_1; - if (IS_LITTLE_ENDIAN) { - *revert = - is_upload ? REVERT_UPLOADING_1_5_5_5 : - REVERT_DOWNLOADING_1_5_5_5; - } - else - *revert = REVERT_NONE; - need_swap_rb = 1; - break; - - case PICT_a1: - *tex_format = GL_ALPHA; - *tex_type = GL_UNSIGNED_BYTE; - *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1; - break; - - case PICT_a8: - *tex_format = GL_ALPHA; - *tex_type = GL_UNSIGNED_BYTE; - *revert = REVERT_NONE; - break; - - case PICT_x4r4g4b4: - *no_alpha = 1; - case PICT_a4r4g4b4: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; - *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; - need_swap_rb = 1; - break; - - case PICT_x4b4g4r4: - *no_alpha = 1; - case PICT_a4b4g4r4: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; - *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; - break; - - default: - LogMessageVerb(X_INFO, 0, - "fail to get matched format for %x \n", format); - return -1; - } - - if (need_swap_rb) - *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING; - else - *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING; - return 0; -} - -static int -glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, - GLenum *format, - GLenum *type, - int *no_alpha, - int *revert, int *swap_rb, int is_upload) -{ - glamor_pixmap_private *pixmap_priv; - PictFormatShort pict_format; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - - pixmap_priv = glamor_get_pixmap_private(pixmap); - if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) - pict_format = pixmap_priv->base.picture->format; - else - pict_format = format_for_depth(pixmap->drawable.depth); - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - return glamor_get_tex_format_type_from_pictformat_gl(pict_format, - format, type, - no_alpha, - revert, - swap_rb, - is_upload); - } else { - return glamor_get_tex_format_type_from_pictformat_gles2(pict_format, - format, type, - no_alpha, - revert, - swap_rb, - is_upload); - } -} - -static void * -_glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, - int stride, int revert) -{ - PictFormatShort dst_format, src_format; - pixman_image_t *dst_image; - pixman_image_t *src_image; - int src_stride; - - if (revert == REVERT_UPLOADING_A1) { - src_format = PICT_a1; - dst_format = PICT_a8; - src_stride = PixmapBytePad(w, 1); - } - else { - dst_format = PICT_a1; - src_format = PICT_a8; - src_stride = (((w * 8 + 7) / 8) + 3) & ~3; - } - - dst_image = pixman_image_create_bits(dst_format, w, h, dst_bits, stride); - if (dst_image == NULL) { - return NULL; - } - - src_image = pixman_image_create_bits(src_format, - w, h, src_bits, src_stride); - - if (src_image == NULL) { - pixman_image_unref(dst_image); - return NULL; - } - - pixman_image_composite(PictOpSrc, src_image, NULL, dst_image, - 0, 0, 0, 0, 0, 0, w, h); - - pixman_image_unref(src_image); - pixman_image_unref(dst_image); - return dst_bits; -} - -#define ADJUST_BITS(d, src_bits, dst_bits) (((dst_bits) == (src_bits)) ? (d) : \ - (((dst_bits) > (src_bits)) ? \ - (((d) << ((dst_bits) - (src_bits))) \ - + (( 1 << ((dst_bits) - (src_bits))) >> 1)) \ - : ((d) >> ((src_bits) - (dst_bits))))) - -#define GLAMOR_DO_CONVERT(src, dst, no_alpha, swap, \ - a_shift_src, a_bits_src, \ - b_shift_src, b_bits_src, \ - g_shift_src, g_bits_src, \ - r_shift_src, r_bits_src, \ - a_shift, a_bits, \ - b_shift, b_bits, \ - g_shift, g_bits, \ - r_shift, r_bits) \ - do { \ - typeof(src) a,b,g,r; \ - typeof(src) a_mask_src, b_mask_src, g_mask_src, r_mask_src;\ - a_mask_src = (((1 << (a_bits_src)) - 1) << a_shift_src);\ - b_mask_src = (((1 << (b_bits_src)) - 1) << b_shift_src);\ - g_mask_src = (((1 << (g_bits_src)) - 1) << g_shift_src);\ - r_mask_src = (((1 << (r_bits_src)) - 1) << r_shift_src);\ - if (no_alpha) \ - a = (a_mask_src) >> (a_shift_src); \ - else \ - a = ((src) & (a_mask_src)) >> (a_shift_src); \ - b = ((src) & (b_mask_src)) >> (b_shift_src); \ - g = ((src) & (g_mask_src)) >> (g_shift_src); \ - r = ((src) & (r_mask_src)) >> (r_shift_src); \ - a = ADJUST_BITS(a, a_bits_src, a_bits); \ - b = ADJUST_BITS(b, b_bits_src, b_bits); \ - g = ADJUST_BITS(g, g_bits_src, g_bits); \ - r = ADJUST_BITS(r, r_bits_src, r_bits); \ - if (swap == 0) \ - (*dst) = ((a) << (a_shift)) | ((b) << (b_shift)) | ((g) << (g_shift)) | ((r) << (r_shift)); \ - else \ - (*dst) = ((a) << (a_shift)) | ((r) << (b_shift)) | ((g) << (g_shift)) | ((b) << (r_shift)); \ - } while (0) - -static void * -_glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h, - int stride, int no_alpha, int revert, - int swap_rb) -{ - int x, y; - unsigned int *words, *saved_words, *source_words; - int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || - swap_rb == SWAP_NONE_UPLOADING); - - source_words = src_bits; - words = dst_bits; - saved_words = words; - - for (y = 0; y < h; y++) { - DEBUGF("Line %d : ", y); - for (x = 0; x < w; x++) { - unsigned int pixel = source_words[x]; - - if (revert == REVERT_DOWNLOADING_2_10_10_10) - GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, - 24, 8, 16, 8, 8, 8, 0, 8, - 30, 2, 20, 10, 10, 10, 0, 10); - else - GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, - 30, 2, 20, 10, 10, 10, 0, 10, - 24, 8, 16, 8, 8, 8, 0, 8); - DEBUGF("%x:%x ", pixel, words[x]); - } - DEBUGF("\n"); - words += stride / sizeof(*words); - source_words += stride / sizeof(*words); - } - DEBUGF("\n"); - return saved_words; - -} - -static void * -_glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h, - int stride, int no_alpha, int revert, int swap_rb) -{ - int x, y; - unsigned short *words, *saved_words, *source_words; - int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || - swap_rb == SWAP_NONE_UPLOADING); - - words = dst_bits; - source_words = src_bits; - saved_words = words; - - for (y = 0; y < h; y++) { - DEBUGF("Line %d : ", y); - for (x = 0; x < w; x++) { - unsigned short pixel = source_words[x]; - - if (revert == REVERT_DOWNLOADING_1_5_5_5) - GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, - 0, 1, 1, 5, 6, 5, 11, 5, - 15, 1, 10, 5, 5, 5, 0, 5); - else - GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, - 15, 1, 10, 5, 5, 5, 0, 5, - 0, 1, 1, 5, 6, 5, 11, 5); - DEBUGF("%04x:%04x ", pixel, words[x]); - } - DEBUGF("\n"); - words += stride / sizeof(*words); - source_words += stride / sizeof(*words); - } - DEBUGF("\n"); - return saved_words; -} - -/* - * This function is to convert an unsupported color format to/from a - * supported GL format. - * Here are the current scenarios: - * - * @no_alpha: - * If it is set, then we need to wire the alpha value to 1. - * @revert: - REVERT_DOWNLOADING_A1 : convert an Alpha8 buffer to a A1 buffer. - REVERT_UPLOADING_A1 : convert an A1 buffer to an Alpha8 buffer - REVERT_DOWNLOADING_2_10_10_10 : convert r10G10b10X2 to X2B10G10R10 - REVERT_UPLOADING_2_10_10_10 : convert X2B10G10R10 to R10G10B10X2 - REVERT_DOWNLOADING_1_5_5_5 : convert B5G5R5X1 to X1R5G5B5 - REVERT_UPLOADING_1_5_5_5 : convert X1R5G5B5 to B5G5R5X1 - @swap_rb: if we have the swap_rb set, then we need to swap the R and B's position. - * - */ - -static void * -glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, - int stride, int no_alpha, int revert, int swap_rb) -{ - if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) { - return _glamor_color_convert_a1_a8(src_bits, dst_bits, w, h, stride, - revert); - } - else if (revert == REVERT_DOWNLOADING_2_10_10_10 || - revert == REVERT_UPLOADING_2_10_10_10) { - return _glamor_color_revert_x2b10g10r10(src_bits, dst_bits, w, h, - stride, no_alpha, revert, - swap_rb); - } - else if (revert == REVERT_DOWNLOADING_1_5_5_5 || - revert == REVERT_UPLOADING_1_5_5_5) { - return _glamor_color_revert_x1b5g5r5(src_bits, dst_bits, w, h, stride, - no_alpha, revert, swap_rb); - } - else - ErrorF("convert a non-supported mode %x.\n", revert); - - return NULL; -} - -/** - * Upload pixmap to a specified texture. - * This texture may not be the one attached to it. - **/ -static void -__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, - GLenum format, - GLenum type, - int x, int y, int w, int h, - void *bits, int pbo) -{ - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - int non_sub = 0; - unsigned int iformat = 0; - - glamor_make_current(glamor_priv); - if (*tex == 0) { - glGenTextures(1, tex); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - iformat = gl_iformat_for_pixmap(pixmap); - else - iformat = format; - non_sub = 1; - assert(x == 0 && y == 0); - } - - 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); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - - assert(pbo || bits != 0); - if (bits == NULL) { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - } - if (non_sub) - glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits); - else - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits); - - if (bits == NULL) - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); -} - -static Bool -_glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, - GLenum type, int no_alpha, int revert, - int swap_rb, int x, int y, int w, int h, - int stride, void *bits, int pbo) -{ - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - static float vertices[8]; - - static float texcoords_inv[8] = { 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - float *ptexcoords; - float dst_xscale, dst_yscale; - GLuint tex = 0; - int need_free_bits = 0; - - if (bits == NULL) - goto ready_to_upload; - - if (revert > REVERT_NORMAL) { - /* XXX if we are restoring the pixmap, then we may not need to allocate - * new buffer */ - void *converted_bits; - - if (pixmap->drawable.depth == 1) - stride = (((w * 8 + 7) / 8) + 3) & ~3; - - converted_bits = malloc(h * stride); - - if (converted_bits == NULL) - return FALSE; - bits = glamor_color_convert_to_bits(bits, converted_bits, w, h, - stride, no_alpha, revert, swap_rb); - if (bits == NULL) { - free(converted_bits); - ErrorF("Failed to convert pixmap no_alpha %d," - "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb); - return FALSE; - } - no_alpha = 0; - revert = REVERT_NONE; - swap_rb = SWAP_NONE_UPLOADING; - need_free_bits = TRUE; - } - - ready_to_upload: - - /* Try fast path firstly, upload the pixmap to the texture attached - * to the fbo directly. */ - if (no_alpha == 0 - && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING -#ifdef WALKAROUND_LARGE_TEXTURE_MAP - && pixmap_priv->type != GLAMOR_TEXTURE_LARGE -#endif - ) { - int fbo_x_off, fbo_y_off; - - assert(pixmap_priv->base.fbo->tex); - pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); - - assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0); - assert(x + fbo_x_off + w <= pixmap_priv->base.fbo->width); - assert(y + fbo_y_off + h <= pixmap_priv->base.fbo->height); - __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex, - format, type, - x + fbo_x_off, y + fbo_y_off, w, h, - bits, pbo); - } else { - ptexcoords = texcoords_inv; - - pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale); - glamor_set_normalize_vcoords(pixmap_priv, dst_xscale, - dst_yscale, - x, y, - x + w, y + h, - vertices); - /* Slow path, we need to flip y or wire alpha to 1. */ - glamor_make_current(glamor_priv); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), ptexcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - __glamor_upload_pixmap_to_texture(pixmap, &tex, - format, type, 0, 0, w, h, bits, pbo); - glActiveTexture(GL_TEXTURE0); - 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); - glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert); - glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glDeleteTextures(1, &tex); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } - - if (need_free_bits) - free(bits); - return TRUE; -} - -/* - * Prepare to upload a pixmap to texture memory. - * no_alpha equals 1 means the format needs to wire alpha to 1. - */ -static int -glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, - int revert, int swap_rb) -{ - int flag = 0; - glamor_pixmap_private *pixmap_priv; - glamor_screen_private *glamor_priv; - glamor_pixmap_fbo *fbo; - GLenum iformat; - - pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - - if (pixmap_priv->base.gl_fbo != GLAMOR_FBO_UNATTACHED) - return 0; - - if (pixmap_priv->base.fbo - && (pixmap_priv->base.fbo->width < pixmap->drawable.width - || pixmap_priv->base.fbo->height < pixmap->drawable.height)) { - fbo = glamor_pixmap_detach_fbo(pixmap_priv); - glamor_destroy_fbo(fbo); - } - - if (pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb) - return 0; - - if (!(no_alpha || (revert == REVERT_NORMAL) - || (swap_rb != SWAP_NONE_UPLOADING))) { - /* We don't need a fbo, a simple texture uploading should work. */ - - flag = GLAMOR_CREATE_FBO_NO_FBO; - } - - if ((flag == GLAMOR_CREATE_FBO_NO_FBO - && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) - || (flag == 0 && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) - return 0; - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - iformat = gl_iformat_for_pixmap(pixmap); - else - iformat = format; - - if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag)) - return -1; - - return 0; -} - -/* - * upload sub region to a large region. - * */ -static void -glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits, - int src_stride, int bpp, int x, int y, int w, int h) -{ - int j; - int byte_per_pixel; - - byte_per_pixel = bpp / 8; - src_bits += y * src_stride + (x * byte_per_pixel); - - for (j = y; j < y + h; j++) { - memcpy(dst_bits, src_bits, w * byte_per_pixel); - src_bits += src_stride; - dst_bits += dst_stride; - } -} - -Bool -glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, - int h, int stride, void *bits, int pbo) -{ - GLenum format, type; - int no_alpha, revert, swap_rb; - glamor_pixmap_private *pixmap_priv; - Bool force_clip; - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &revert, &swap_rb, 1)) { - glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); - return FALSE; - } - if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) - return FALSE; - - pixmap_priv = glamor_get_pixmap_private(pixmap); - force_clip = pixmap_priv->base.glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP - && !glamor_check_fbo_size(pixmap_priv->base.glamor_priv, w, h); - - if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE || force_clip) { - RegionRec region; - BoxRec box; - int n_region; - glamor_pixmap_clipped_regions *clipped_regions; - void *sub_bits; - int i, j; - - sub_bits = malloc(h * stride); - if (sub_bits == NULL) - return FALSE; - box.x1 = x; - box.y1 = y; - box.x2 = x + w; - box.y2 = y + h; - RegionInitBoxes(®ion, &box, 1); - if (!force_clip) - clipped_regions = - glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, - 0, 0, 0); - else - clipped_regions = - glamor_compute_clipped_regions_ext(pixmap_priv, ®ion, - &n_region, - pixmap_priv->large.block_w, - pixmap_priv->large.block_h, - 0, - 0); - DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap); - for (i = 0; i < n_region; i++) { - BoxPtr boxes; - int nbox; - int temp_stride; - void *temp_bits; - - assert(pbo == 0); - - glamor_set_pixmap_fbo_current(pixmap_priv, clipped_regions[i].block_idx); - - boxes = RegionRects(clipped_regions[i].region); - nbox = RegionNumRects(clipped_regions[i].region); - DEBUGF("split to %d boxes\n", nbox); - for (j = 0; j < nbox; j++) { - temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1, - pixmap->drawable.depth); - - if (boxes[j].x1 == x && temp_stride == stride) { - temp_bits = (char *) bits + (boxes[j].y1 - y) * stride; - } - else { - temp_bits = sub_bits; - glamor_put_bits(temp_bits, temp_stride, bits, stride, - pixmap->drawable.bitsPerPixel, - boxes[j].x1 - x, boxes[j].y1 - y, - boxes[j].x2 - boxes[j].x1, - boxes[j].y2 - boxes[j].y1); - } - DEBUGF("upload x %d y %d w %d h %d temp stride %d \n", - boxes[j].x1 - x, boxes[j].y1 - y, - boxes[j].x2 - boxes[j].x1, - boxes[j].y2 - boxes[j].y1, temp_stride); - if (_glamor_upload_bits_to_pixmap_texture - (pixmap, format, type, no_alpha, revert, swap_rb, - boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1, - boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits, - pbo) == FALSE) { - RegionUninit(®ion); - free(sub_bits); - assert(0); - return FALSE; - } - } - RegionDestroy(clipped_regions[i].region); - } - free(sub_bits); - free(clipped_regions); - RegionUninit(®ion); - return TRUE; - } - else - return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, - no_alpha, revert, swap_rb, - x, y, w, h, stride, bits, - pbo); -} - -enum glamor_pixmap_status -glamor_upload_pixmap_to_texture(PixmapPtr pixmap) -{ - glamor_pixmap_private *pixmap_priv; - void *data; - int pbo; - int ret; - - pixmap_priv = glamor_get_pixmap_private(pixmap); - - if ((pixmap_priv->base.fbo) - && (pixmap_priv->base.fbo->pbo_valid)) { - data = NULL; - pbo = pixmap_priv->base.fbo->pbo; - } - else { - data = pixmap->devPrivate.ptr; - pbo = 0; - } - - if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0, - pixmap->drawable.width, - pixmap->drawable.height, - pixmap->devKind, data, pbo)) - ret = GLAMOR_UPLOAD_DONE; - else - ret = GLAMOR_UPLOAD_FAILED; - - return ret; -} - -/* - * as gles2 only support a very small set of color format and - * type when do glReadPixel, - * Before we use glReadPixels to get back a textured pixmap, - * Use shader to convert it to a supported format and thus - * get a new temporary pixmap returned. - * */ - -glamor_pixmap_fbo * -glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, - GLenum format, GLenum type, int no_alpha, - int revert, int swap_rb) -{ - glamor_pixmap_private *source_priv; - glamor_screen_private *glamor_priv; - ScreenPtr screen; - glamor_pixmap_fbo *temp_fbo; - float temp_xscale, temp_yscale, source_xscale, source_yscale; - static float vertices[8]; - static float texcoords[8]; - - screen = source->drawable.pScreen; - - glamor_priv = glamor_get_screen_private(screen); - source_priv = glamor_get_pixmap_private(source); - temp_fbo = glamor_create_fbo(glamor_priv, w, h, format, 0); - if (temp_fbo == NULL) - return NULL; - - glamor_make_current(glamor_priv); - temp_xscale = 1.0 / w; - temp_yscale = 1.0 / h; - - glamor_set_normalize_vcoords((struct glamor_pixmap_private *) NULL, - temp_xscale, temp_yscale, 0, 0, w, h, - vertices); - - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - - pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale); - glamor_set_normalize_tcoords(source_priv, source_xscale, - source_yscale, - x, y, - x + w, y + h, - texcoords); - - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), texcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, source_priv->base.fbo->tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glamor_set_destination_pixmap_fbo(temp_fbo, 0, 0, w, h); - glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert); - glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - return temp_fbo; -} - -/* fixup a fbo to the exact size as the pixmap. */ -/* XXX LARGE pixmap? */ -Bool -glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) -{ - glamor_pixmap_fbo *old_fbo; - glamor_pixmap_fbo *new_fbo = NULL; - PixmapPtr scratch = NULL; - glamor_pixmap_private *scratch_priv; - DrawablePtr drawable; - GCPtr gc = NULL; - int ret = FALSE; - - drawable = &pixmap_priv->base.pixmap->drawable; - - if (!GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv)) - return TRUE; - - old_fbo = pixmap_priv->base.fbo; - - if (!old_fbo) - return FALSE; - - gc = GetScratchGC(drawable->depth, screen); - if (!gc) - goto fail; - - scratch = glamor_create_pixmap(screen, drawable->width, drawable->height, - drawable->depth, GLAMOR_CREATE_PIXMAP_FIXUP); - - scratch_priv = glamor_get_pixmap_private(scratch); - - if (!scratch_priv->base.fbo) - goto fail; - - ValidateGC(&scratch->drawable, gc); - glamor_copy_area(drawable, - &scratch->drawable, - gc, 0, 0, drawable->width, drawable->height, 0, 0); - old_fbo = glamor_pixmap_detach_fbo(pixmap_priv); - new_fbo = glamor_pixmap_detach_fbo(scratch_priv); - glamor_pixmap_attach_fbo(pixmap_priv->base.pixmap, new_fbo); - glamor_pixmap_attach_fbo(scratch, old_fbo); - - DEBUGF("old %dx%d type %d\n", - drawable->width, drawable->height, pixmap_priv->type); - DEBUGF("copy tex %d %dx%d to tex %d %dx%d \n", - old_fbo->tex, old_fbo->width, old_fbo->height, new_fbo->tex, - new_fbo->width, new_fbo->height); - ret = TRUE; - fail: - if (gc) - FreeScratchGC(gc); - if (scratch) - glamor_destroy_pixmap(scratch); - - return ret; -} diff --git a/xserver/glamor/glamor_points.c b/xserver/glamor/glamor_points.c index 84383d254..facfe8240 100644 --- a/xserver/glamor/glamor_points.c +++ b/xserver/glamor/glamor_points.c @@ -46,7 +46,7 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint int off_x, off_y; GLshort *vbo_ppt; char *vbo_offset; - int box_x, box_y; + int box_index; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -55,17 +55,18 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint glamor_make_current(glamor_priv); if (prog->failed) - goto bail_ctx; + goto bail; if (!prog->prog) { if (!glamor_build_program(screen, prog, &glamor_facet_point, - &glamor_fill_solid)) - goto bail_ctx; + &glamor_fill_solid, + NULL, NULL)) + goto bail; } if (!glamor_use_program(pixmap, gc, prog, NULL)) - goto bail_ctx; + goto bail; vbo_ppt = glamor_get_vbo_space(screen, npt * (2 * sizeof (INT16)), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); @@ -85,11 +86,12 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); - glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE, prog->matrix_uniform, &off_x, &off_y); + glamor_set_destination_drawable(drawable, box_index, TRUE, TRUE, + prog->matrix_uniform, &off_x, &off_y); while (nbox--) { glScissor(box->x1 + off_x, @@ -102,13 +104,10 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint } glDisable(GL_SCISSOR_TEST); - glDisable(GL_COLOR_LOGIC_OP); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); return TRUE; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } @@ -121,18 +120,3 @@ glamor_poly_point(DrawablePtr drawable, GCPtr gc, int mode, int npt, return; miPolyPoint(drawable, gc, mode, npt, ppt); } - -Bool -glamor_poly_point_nf(DrawablePtr drawable, GCPtr gc, int mode, int npt, - DDXPointPtr ppt) -{ - if (glamor_poly_point_gl(drawable, gc, mode, npt, ppt)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) - return FALSE; - - miPolyPoint(drawable, gc, mode, npt, ppt); - return TRUE; -} - diff --git a/xserver/glamor/glamor_prepare.c b/xserver/glamor/glamor_prepare.c index 40b7b4feb..5a73e6c7d 100644 --- a/xserver/glamor/glamor_prepare.c +++ b/xserver/glamor/glamor_prepare.c @@ -56,7 +56,7 @@ glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box) * we'll assume that it's directly mapped * by a lower level driver */ - if (!priv->base.prepared) + if (!priv->prepared) return TRUE; /* In X, multiple Drawables can be stored in the same Pixmap (such as @@ -67,38 +67,38 @@ glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box) * As a result, when doing a series of mappings for a fallback, we may * need to add more boxes to the set of data we've downloaded, as we go. */ - RegionSubtract(®ion, ®ion, &priv->base.prepare_region); + RegionSubtract(®ion, ®ion, &priv->prepare_region); if (!RegionNotEmpty(®ion)) return TRUE; if (access == GLAMOR_ACCESS_RW) FatalError("attempt to remap buffer as writable"); - if (priv->base.pbo) { - glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo); + if (priv->pbo) { + glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->pbo); glUnmapBuffer(GL_PIXEL_PACK_BUFFER); pixmap->devPrivate.ptr = NULL; } } else { - RegionInit(&priv->base.prepare_region, box, 1); + RegionInit(&priv->prepare_region, box, 1); if (glamor_priv->has_rw_pbo) { - if (priv->base.pbo == 0) - glGenBuffers(1, &priv->base.pbo); + if (priv->pbo == 0) + glGenBuffers(1, &priv->pbo); gl_usage = GL_STREAM_READ; - glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo); + glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->pbo); glBufferData(GL_PIXEL_PACK_BUFFER, pixmap->devKind * pixmap->drawable.height, NULL, gl_usage); } else { - pixmap->devPrivate.ptr = malloc(pixmap->devKind * - pixmap->drawable.height); + pixmap->devPrivate.ptr = xallocarray(pixmap->devKind, + pixmap->drawable.height); if (!pixmap->devPrivate.ptr) return FALSE; } - priv->base.map_access = access; + priv->map_access = access; } glamor_download_boxes(pixmap, RegionRects(®ion), RegionNumRects(®ion), @@ -107,7 +107,7 @@ glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box) RegionUninit(®ion); if (glamor_priv->has_rw_pbo) { - if (priv->base.map_access == GLAMOR_ACCESS_RW) + if (priv->map_access == GLAMOR_ACCESS_RW) gl_access = GL_READ_WRITE; else gl_access = GL_READ_ONLY; @@ -116,7 +116,7 @@ glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box) glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); } - priv->base.prepared = TRUE; + priv->prepared = TRUE; return TRUE; } @@ -135,34 +135,34 @@ glamor_fini_pixmap(PixmapPtr pixmap) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) return; - if (!priv->base.prepared) + if (!priv->prepared) return; if (glamor_priv->has_rw_pbo) { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->base.pbo); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->pbo); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); pixmap->devPrivate.ptr = NULL; } - if (priv->base.map_access == GLAMOR_ACCESS_RW) { + if (priv->map_access == GLAMOR_ACCESS_RW) { glamor_upload_boxes(pixmap, - RegionRects(&priv->base.prepare_region), - RegionNumRects(&priv->base.prepare_region), + RegionRects(&priv->prepare_region), + RegionNumRects(&priv->prepare_region), 0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind); } - RegionUninit(&priv->base.prepare_region); + RegionUninit(&priv->prepare_region); if (glamor_priv->has_rw_pbo) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glDeleteBuffers(1, &priv->base.pbo); - priv->base.pbo = 0; + glDeleteBuffers(1, &priv->pbo); + priv->pbo = 0; } else { free(pixmap->devPrivate.ptr); pixmap->devPrivate.ptr = NULL; } - priv->base.prepared = FALSE; + priv->prepared = FALSE; } Bool @@ -222,8 +222,22 @@ glamor_prepare_access_picture_box(PicturePtr picture, glamor_access_t access, { if (!picture || !picture->pDrawable) return TRUE; - return glamor_prepare_access_box(picture->pDrawable, access, - x, y, w, h); + + /* If a transform is set, we don't know what the bounds is on the + * source, so just prepare the whole pixmap. XXX: We could + * potentially work out where in the source would be sampled based + * on the transform, and we don't need do do this for destination + * pixmaps at all. + */ + if (picture->transform) { + return glamor_prepare_access_box(picture->pDrawable, access, + 0, 0, + picture->pDrawable->width, + picture->pDrawable->height); + } else { + return glamor_prepare_access_box(picture->pDrawable, access, + x, y, w, h); + } } void diff --git a/xserver/glamor/glamor_priv.h b/xserver/glamor/glamor_priv.h index 612701a19..a70f10eb4 100644 --- a/xserver/glamor/glamor_priv.h +++ b/xserver/glamor/glamor_priv.h @@ -48,9 +48,7 @@ "precision mediump float;\n" \ "#endif\n" -#ifdef RENDER #include "glyphstr.h" -#endif #include "glamor_debug.h" #include "glamor_context.h" @@ -74,7 +72,7 @@ typedef struct glamor_composite_shader { union { float source_solid_color[4]; struct { - struct glamor_pixmap_private *source_priv; + PixmapPtr source_pixmap; PicturePtr source; }; }; @@ -82,12 +80,18 @@ typedef struct glamor_composite_shader { union { float mask_solid_color[4]; struct { - struct glamor_pixmap_private *mask_priv; + PixmapPtr mask_pixmap; PicturePtr mask; }; }; } glamor_composite_shader; +enum ca_state { + CA_NONE, + CA_TWO_PASS, + CA_DUAL_BLEND, +}; + enum shader_source { SHADER_SOURCE_SOLID, SHADER_SOURCE_TEXTURE, @@ -103,18 +107,17 @@ enum shader_mask { SHADER_MASK_COUNT, }; -enum shader_in { - SHADER_IN_SOURCE_ONLY, - SHADER_IN_NORMAL, - SHADER_IN_CA_SOURCE, - SHADER_IN_CA_ALPHA, - SHADER_IN_COUNT, +enum shader_dest_swizzle { + SHADER_DEST_SWIZZLE_DEFAULT, + SHADER_DEST_SWIZZLE_ALPHA_TO_RED, + SHADER_DEST_SWIZZLE_COUNT, }; struct shader_key { enum shader_source source; enum shader_mask mask; - enum shader_in in; + glamor_program_alpha in; + enum shader_dest_swizzle dest_swizzle; }; struct blendinfo { @@ -156,41 +159,8 @@ enum glamor_gl_flavor { GLAMOR_GL_ES2 // OPENGL ES2.0 API }; -#define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 - #define GLAMOR_COMPOSITE_VBO_VERT_CNT (64*1024) -typedef struct { - PicturePtr picture; /* Where the glyphs of the cache are stored */ - GlyphPtr *glyphs; - uint16_t count; - uint16_t evict; -} glamor_glyph_cache_t; - -#define CACHE_PICTURE_SIZE 1024 -#define GLYPH_MIN_SIZE 8 -#define GLYPH_MAX_SIZE 64 -#define GLYPH_CACHE_SIZE ((CACHE_PICTURE_SIZE) * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE)) - -#define MASK_CACHE_MAX_SIZE 32 -#define MASK_CACHE_WIDTH (CACHE_PICTURE_SIZE / MASK_CACHE_MAX_SIZE) -#define MASK_CACHE_MASK ((1LL << (MASK_CACHE_WIDTH)) - 1) - -struct glamor_glyph_mask_cache_entry { - int idx; - int width; - int height; - int x; - int y; -}; - -typedef struct { - PixmapPtr pixmap; - struct glamor_glyph_mask_cache_entry mcache[MASK_CACHE_WIDTH]; - unsigned int free_bitmap; - unsigned int cleared_bitmap; -} glamor_glyph_mask_cache_t; - struct glamor_saved_procs { CloseScreenProcPtr close_screen; CreateScreenResourcesProcPtr create_screen_resources; @@ -208,10 +178,6 @@ struct glamor_saved_procs { BitmapToRegionProcPtr bitmap_to_region; TrianglesProcPtr triangles; AddTrapsProcPtr addtraps; - CreatePictureProcPtr create_picture; - DestroyPictureProcPtr destroy_picture; - UnrealizeGlyphProcPtr unrealize_glyph; - SetWindowPixmapProcPtr set_window_pixmap; #if XSYNC SyncScreenFuncsRec sync_screen_funcs; #endif @@ -230,16 +196,22 @@ typedef struct glamor_screen_private { unsigned int tick; enum glamor_gl_flavor gl_flavor; int glsl_version; - int has_pack_invert; - int has_fbo_blit; - int has_map_buffer_range; - int has_buffer_storage; - int has_khr_debug; - int has_nv_texture_barrier; - int has_pack_subimage; - int has_unpack_subimage; + Bool has_pack_invert; + Bool has_fbo_blit; + Bool has_map_buffer_range; + Bool has_buffer_storage; + Bool has_khr_debug; + Bool has_nv_texture_barrier; + Bool has_pack_subimage; + Bool has_unpack_subimage; + Bool has_rw_pbo; + Bool use_quads; + Bool has_vertex_array_object; + Bool has_dual_blend; + Bool is_core_profile; int max_fbo_size; - int has_rw_pbo; + + GLuint one_channel_format; struct xorg_list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; @@ -276,11 +248,21 @@ typedef struct glamor_screen_private { glamor_program_fill on_off_dash_line_progs; glamor_program double_dash_line_prog; - /* vertext/elment_index buffer object for render */ - GLuint vbo, ebo; + /* glamor composite_glyphs shaders */ + glamor_program_render glyphs_program; + struct glamor_glyph_atlas *glyph_atlas_a; + struct glamor_glyph_atlas *glyph_atlas_argb; + int glyph_atlas_dim; + int glyph_max_dim; + char *glyph_defines; + + /** Vertex buffer for all GPU rendering. */ + GLuint vao; + GLuint vbo; /** Next offset within the VBO that glamor_get_vbo_space() will use. */ int vbo_offset; int vbo_size; + Bool vbo_mapped; /** * Pointer to glamor_get_vbo_space()'s current VBO mapping. * @@ -289,14 +271,20 @@ typedef struct glamor_screen_private { */ char *vb; int vb_stride; + + /** Cached index buffer for translating GL_QUADS to triangles. */ + GLuint ib; + /** Index buffer type: GL_UNSIGNED_SHORT or GL_UNSIGNED_INT */ + GLenum ib_type; + /** Number of quads the index buffer has indices for. */ + unsigned ib_size; + Bool has_source_coords, has_mask_coords; - int render_nr_verts; + int render_nr_quads; glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT] [SHADER_MASK_COUNT] - [SHADER_IN_COUNT]; - glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; - glamor_glyph_mask_cache_t *mask_cache[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; - Bool glyph_caches_realized; + [glamor_program_alpha_count] + [SHADER_DEST_SWIZZLE_COUNT]; /* shaders to restore a texture to another texture. */ GLint finish_access_prog[2]; @@ -317,8 +305,11 @@ typedef struct glamor_screen_private { ScreenPtr screen; int dri3_enabled; + Bool suppress_gl_out_of_memory_logging; + Bool logged_any_fbo_allocation_failure; + /* xv */ - GLint xv_prog; + glamor_program xv_prog; struct glamor_context ctx; } glamor_screen_private; @@ -336,110 +327,34 @@ enum glamor_fbo_state { * point at anything. */ GLAMOR_FBO_NORMAL, - /** - * The FBO is present and can be accessed as a linear memory - * mapping through devPrivate.ptr. - */ - GLAMOR_FBO_DOWNLOADED, }; -/* glamor_pixmap_fbo: - * @list: to be used to link to the cache pool list. - * @expire: when push to cache pool list, set a expire count. - * will be freed when glamor_priv->tick is equal or - * larger than this expire count in block handler. - * @pbo_valid: The pbo has a valid copy of the pixmap's data. - * @tex: attached texture. - * @fb: attached fbo. - * @pbo: attached pbo. - * @width: width of this fbo. - * @height: height of this fbo. - * @external set when the texture was not created by glamor - * @format: internal format of this fbo's texture. - * @type: internal type of this fbo's texture. - * @glamor_priv: point to glamor private data. - */ typedef struct glamor_pixmap_fbo { - struct xorg_list list; + struct xorg_list list; /**< linked list pointers when in the fbo cache */ + /** glamor_priv->tick number when this FBO will be expired from the cache. */ unsigned int expire; - unsigned char pbo_valid; - GLuint tex; - GLuint fb; - GLuint pbo; - int width; - int height; + GLuint tex; /**< GL texture name */ + GLuint fb; /**< GL FBO name */ + int width; /**< width in pixels */ + int height; /**< height in pixels */ + /** + * Flag for when texture contents might be shared with a + * non-glamor user. + * + * This is used to avoid putting textures used by other clients + * into the FBO cache. + */ Bool external; - GLenum format; - GLenum type; - glamor_screen_private *glamor_priv; + GLenum format; /**< GL format used to create the texture. */ + GLenum type; /**< GL type used to create the texture. */ } glamor_pixmap_fbo; -/* - * glamor_pixmap_private - glamor pixmap's private structure. - * @gl_tex: The pixmap is in a gl texture originally. - * @is_picture: The drawable is attached to a picture. - * @pict_format: the corresponding picture's format. - * @pixmap: The corresponding pixmap's pointer. - * - * For GLAMOR_TEXTURE_LARGE, nbox should larger than 1. - * And the box and fbo will both have nbox elements. - * and box[i] store the relatively coords in this pixmap - * of the fbo[i]. The reason why use boxes not region to - * represent this structure is we may need to use overlapped - * boxes for one pixmap for some special reason. - * - * pixmap - * ****************** - * * fbo0 * fbo1 * - * * * * - * ****************** - * * fbo2 * fbo3 * - * * * * - * ****************** - * - * Let's assume the texture has size of 1024x1024 - * box[0] = {0,0,1024,1024} - * box[1] = {1024,0,2048,2048} - * ... - * - * For GLAMOR_TEXTURE_ATLAS nbox should be 1. And box - * and fbo both has one elements, and the box store - * the relatively coords in the fbo of this pixmap: - * - * fbo - * ****************** - * * pixmap * - * * ********* * - * * * * * - * * ********* * - * * * - * ****************** - * - * Assume the pixmap is at the (100,100) relatively to - * the fbo's origin. - * box[0]={100, 100, 1124, 1124}; - * - * Considering large pixmap is not a normal case, to keep - * it simple, I designe it as the following way. - * When deal with a large pixmap, it split the working - * rectangle into serval boxes, and each box fit into a - * corresponding fbo. And then the rendering function will - * loop from the left-top box to the right-bottom box, - * each time, we will set current box and current fbo - * to the box and fbo elements. Thus the inner routines - * can handle it as normal, only the coords calculation need - * to aware of it's large pixmap. - * - * Currently, we haven't implemented the atlas pixmap. - * - **/ - typedef struct glamor_pixmap_clipped_regions { int block_idx; RegionPtr region; } glamor_pixmap_clipped_regions; -typedef struct glamor_pixmap_private_base { +typedef struct glamor_pixmap_private { glamor_pixmap_type_t type; enum glamor_fbo_state gl_fbo; /** @@ -448,137 +363,170 @@ typedef struct glamor_pixmap_private_base { * that data on glamor_finish_access(). */ glamor_access_t map_access; - unsigned char is_picture:1; - unsigned char gl_tex:1; glamor_pixmap_fbo *fbo; - PixmapPtr pixmap; + /** current fbo's coords in the whole pixmap. */ BoxRec box; - int drm_stride; - glamor_screen_private *glamor_priv; - PicturePtr picture; GLuint pbo; RegionRec prepare_region; Bool prepared; #if GLAMOR_HAS_GBM EGLImageKHR image; #endif -} glamor_pixmap_private_base_t; - -/* - * @base.fbo: current fbo. - * @box: current fbo's coords in the whole pixmap. - * @block_w: block width of this large pixmap. - * @block_h: block height of this large pixmap. - * @block_wcnt: block count in one block row. - * @block_hcnt: block count in one block column. - * @nbox: total block count. - * @box_array: contains each block's corresponding box. - * @fbo_array: contains each block's fbo pointer. - * - **/ -typedef struct glamor_pixmap_private_large { - union { - glamor_pixmap_type_t type; - glamor_pixmap_private_base_t base; - }; - BoxRec box; + /** block width of this large pixmap. */ int block_w; + /** block height of this large pixmap. */ int block_h; + + /** block_wcnt: block count in one block row. */ int block_wcnt; + /** block_hcnt: block count in one block column. */ int block_hcnt; - int nbox; + + /** + * The list of boxes for the bounds of the FBOs making up the + * pixmap. + * + * For a 2048x2048 pixmap with GL FBO size limits of 1024x1024: + * + * ****************** + * * fbo0 * fbo1 * + * * * * + * ****************** + * * fbo2 * fbo3 * + * * * * + * ****************** + * + * box[0] = {0,0,1024,1024} + * box[1] = {1024,0,2048,2048} + * ... + */ BoxPtr box_array; + + /** + * Array of fbo structs containing the actual GL texture/fbo + * names. + */ glamor_pixmap_fbo **fbo_array; -} glamor_pixmap_private_large_t; +} glamor_pixmap_private; + +extern DevPrivateKeyRec glamor_pixmap_private_key; + +static inline glamor_pixmap_private * +glamor_get_pixmap_private(PixmapPtr pixmap) +{ + if (pixmap == NULL) + return NULL; + + return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key); +} /* - * @box: the relative coords in the corresponding fbo. + * Returns TRUE if pixmap has no image object */ -typedef struct glamor_pixmap_private_atlas { - union { - glamor_pixmap_type_t type; - glamor_pixmap_private_base_t base; - }; - BoxRec box; -} glamor_pixmap_private_atlas_t; +static inline Bool +glamor_pixmap_drm_only(PixmapPtr pixmap) +{ + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); -typedef struct glamor_pixmap_private { - union { - glamor_pixmap_type_t type; - glamor_pixmap_private_base_t base; - glamor_pixmap_private_large_t large; - glamor_pixmap_private_atlas_t atlas; - }; -} glamor_pixmap_private; + return priv->type == GLAMOR_DRM_ONLY; +} + +/* + * Returns TRUE if pixmap is plain memory (not a GL object at all) + */ +static inline Bool +glamor_pixmap_is_memory(PixmapPtr pixmap) +{ + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); + + return priv->type == GLAMOR_MEMORY; +} + +/* + * Returns TRUE if pixmap requires multiple textures to hold it + */ +static inline Bool +glamor_pixmap_priv_is_large(glamor_pixmap_private *priv) +{ + return priv->block_wcnt > 1 || priv->block_hcnt > 1; +} + +static inline Bool +glamor_pixmap_priv_is_small(glamor_pixmap_private *priv) +{ + return priv->block_wcnt <= 1 && priv->block_hcnt <= 1; +} + +static inline Bool +glamor_pixmap_is_large(PixmapPtr pixmap) +{ + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); + + return glamor_pixmap_priv_is_large(priv); +} +/* + * Returns TRUE if pixmap has an FBO + */ +static inline Bool +glamor_pixmap_has_fbo(PixmapPtr pixmap) +{ + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); + + return priv->gl_fbo == GLAMOR_FBO_NORMAL; +} static inline void glamor_set_pixmap_fbo_current(glamor_pixmap_private *priv, int idx) { - if (priv->type == GLAMOR_TEXTURE_LARGE) { - priv->large.base.fbo = priv->large.fbo_array[idx]; - priv->large.box = priv->large.box_array[idx]; + if (glamor_pixmap_priv_is_large(priv)) { + priv->fbo = priv->fbo_array[idx]; + priv->box = priv->box_array[idx]; } } static inline glamor_pixmap_fbo * -glamor_pixmap_fbo_at(glamor_pixmap_private *priv, int x, int y) +glamor_pixmap_fbo_at(glamor_pixmap_private *priv, int box) { - if (priv->type == GLAMOR_TEXTURE_LARGE) { - assert(x < priv->large.block_wcnt); - assert(y < priv->large.block_hcnt); - return priv->large.fbo_array[y * priv->large.block_wcnt + x]; - } - assert (x == 0); - assert (y == 0); - return priv->base.fbo; + assert(box < priv->block_wcnt * priv->block_hcnt); + return priv->fbo_array[box]; } static inline BoxPtr -glamor_pixmap_box_at(glamor_pixmap_private *priv, int x, int y) +glamor_pixmap_box_at(glamor_pixmap_private *priv, int box) { - if (priv->type == GLAMOR_TEXTURE_LARGE) { - assert(x < priv->large.block_wcnt); - assert(y < priv->large.block_hcnt); - return &priv->large.box_array[y * priv->large.block_wcnt + x]; - } - assert (x == 0); - assert (y == 0); - return &priv->base.box; + assert(box < priv->block_wcnt * priv->block_hcnt); + return &priv->box_array[box]; } static inline int glamor_pixmap_wcnt(glamor_pixmap_private *priv) { - if (priv->type == GLAMOR_TEXTURE_LARGE) - return priv->large.block_wcnt; - return 1; + return priv->block_wcnt; } static inline int glamor_pixmap_hcnt(glamor_pixmap_private *priv) { - if (priv->type == GLAMOR_TEXTURE_LARGE) - return priv->large.block_hcnt; - return 1; + return priv->block_hcnt; } -#define glamor_pixmap_loop(priv, x, y) \ - for (y = 0; y < glamor_pixmap_hcnt(priv); y++) \ - for (x = 0; x < glamor_pixmap_wcnt(priv); x++) +#define glamor_pixmap_loop(priv, box_index) \ + for (box_index = 0; box_index < glamor_pixmap_hcnt(priv) * \ + glamor_pixmap_wcnt(priv); box_index++) \ -/* - * Pixmap dynamic status, used by dynamic upload feature. - * - * GLAMOR_NONE: initial status, don't need to do anything. - * GLAMOR_UPLOAD_PENDING: marked as need to be uploaded to gl texture. - * GLAMOR_UPLOAD_DONE: the pixmap has been uploaded successfully. - * GLAMOR_UPLOAD_FAILED: fail to upload the pixmap. - * - * */ +/** + * Pixmap upload status, used by glamor_render.c's support for + * temporarily uploading pixmaps to GL textures to get a Composite + * operation done. + */ typedef enum glamor_pixmap_status { + /** initial status, don't need to do anything. */ GLAMOR_NONE, + /** marked as need to be uploaded to gl texture. */ GLAMOR_UPLOAD_PENDING, + /** the pixmap has been uploaded successfully. */ GLAMOR_UPLOAD_DONE, + /** fail to upload the pixmap. */ GLAMOR_UPLOAD_FAILED } glamor_pixmap_status_t; @@ -592,7 +540,6 @@ typedef struct { extern DevPrivateKeyRec glamor_gc_private_key; extern DevPrivateKeyRec glamor_screen_private_key; -extern DevPrivateKeyRec glamor_pixmap_private_key; static inline glamor_screen_private * glamor_get_screen_private(ScreenPtr screen) @@ -607,22 +554,6 @@ glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv) dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv); } -static inline glamor_pixmap_private * -glamor_get_pixmap_private(PixmapPtr pixmap) -{ - glamor_pixmap_private *priv; - - priv = dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key); - if (!priv) { - glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); - priv = dixLookupPrivate(&pixmap->devPrivates, - &glamor_pixmap_private_key); - } - return priv; -} - -void glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv); - static inline glamor_gc_private * glamor_get_gc_private(GCPtr gc) { @@ -634,10 +565,10 @@ glamor_get_gc_private(GCPtr gc) * pixel values for pDrawable. */ static inline Bool -glamor_pm_is_solid(DrawablePtr drawable, unsigned long planemask) +glamor_pm_is_solid(int depth, unsigned long planemask) { - return (planemask & FbFullMask(drawable->depth)) == - FbFullMask(drawable->depth); + return (planemask & FbFullMask(depth)) == + FbFullMask(depth); } extern int glamor_debug_level; @@ -654,9 +585,9 @@ glamor_pixmap_fbo *glamor_create_fbo_from_tex(glamor_screen_private * int flag); glamor_pixmap_fbo *glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag); -void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); -void glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv); - +void glamor_destroy_fbo(glamor_screen_private *glamor_priv, + glamor_pixmap_fbo *fbo); +void glamor_pixmap_destroy_fbo(PixmapPtr pixmap); void glamor_init_pixmap_fbo(ScreenPtr screen); void glamor_fini_pixmap_fbo(ScreenPtr screen); Bool glamor_pixmap_fbo_fixup(ScreenPtr screen, PixmapPtr pixmap); @@ -667,9 +598,11 @@ glamor_pixmap_fbo *glamor_create_fbo_array(glamor_screen_private *glamor_priv, int flag, int block_w, int block_h, glamor_pixmap_private *); +void glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv, + unsigned count); + /* glamor_core.c */ void glamor_init_finish_access_shaders(ScreenPtr screen); -void glamor_fini_finish_access_shaders(ScreenPtr screen); Bool glamor_get_drawable_location(const DrawablePtr drawable); void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, @@ -681,45 +614,29 @@ void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, GLfloat *color); int glamor_set_destination_pixmap(PixmapPtr pixmap); -int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv); -void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *, int, int, int, int); +int glamor_set_destination_pixmap_priv(glamor_screen_private *glamor_priv, PixmapPtr pixmap, glamor_pixmap_private *pixmap_priv); +void glamor_set_destination_pixmap_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *, int, int, int, int); /* nc means no check. caller must ensure this pixmap has valid fbo. * usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly. * */ -void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv); - -glamor_pixmap_fbo *glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, - int y, int w, int h, - GLenum format, GLenum type, - int no_alpha, int revert, - int swap_rb); +void glamor_set_destination_pixmap_priv_nc(glamor_screen_private *glamor_priv, PixmapPtr pixmap, glamor_pixmap_private *pixmap_priv); Bool glamor_set_alu(ScreenPtr screen, unsigned char alu); -Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); +Bool glamor_set_planemask(int depth, unsigned long planemask); RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap); void glamor_track_stipple(GCPtr gc); -/* glamor_glyphs.c */ -Bool glamor_realize_glyph_caches(ScreenPtr screen); -void glamor_glyphs_fini(ScreenPtr screen); -void glamor_glyphs(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs); - /* glamor_render.c */ Bool glamor_composite_clipped_region(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - glamor_pixmap_private *soruce_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, + PixmapPtr source_pixmap, + PixmapPtr mask_pixmap, + PixmapPtr dest_pixmap, RegionPtr region, int x_source, int y_source, @@ -736,38 +653,9 @@ void glamor_composite(CARD8 op, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); -void glamor_init_composite_shaders(ScreenPtr screen); -void glamor_fini_composite_shaders(ScreenPtr screen); -void glamor_composite_glyph_rects(CARD8 op, - PicturePtr src, PicturePtr mask, - PicturePtr dst, int nrect, - glamor_composite_rect_t *rects); void glamor_composite_rects(CARD8 op, PicturePtr pDst, xRenderColor *color, int nRect, xRectangle *rects); -PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, - PicturePtr source, - int x_source, - int y_source, int width, int height); - -Bool glamor_composite_choose_shader(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, - struct shader_key *s_key, - glamor_composite_shader ** shader, - struct blendinfo *op_info, - PictFormatShort *psaved_source_format); - -void glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, - struct shader_key *key, - glamor_composite_shader *shader, - struct blendinfo *op_info); - -void *glamor_setup_composite_vbo(ScreenPtr screen, int n_verts); /* glamor_trapezoid.c */ void glamor_trapezoids(CARD8 op, @@ -777,7 +665,6 @@ void glamor_trapezoids(CARD8 op, /* glamor_gradient.c */ void glamor_init_gradient_shader(ScreenPtr screen); -void glamor_fini_gradient_shader(ScreenPtr screen); PicturePtr glamor_generate_linear_gradient_picture(ScreenPtr screen, PicturePtr src_picture, int x_source, int y_source, @@ -821,44 +708,25 @@ glamor_put_vbo_space(ScreenPtr screen); */ Bool glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag); -/** - * Upload a pixmap to gl texture. Used by dynamic pixmap - * uploading feature. The pixmap must be a software pixmap. - * This function will change current FBO and current shaders. - */ -enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap); - -Bool glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, - int h, int stride, void *bits, - int pbo); - glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions(glamor_pixmap_private *priv, +glamor_compute_clipped_regions(PixmapPtr pixmap, RegionPtr region, int *clipped_nbox, int repeat_type, int reverse, int upsidedown); glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, +glamor_compute_clipped_regions_ext(PixmapPtr pixmap, RegionPtr region, int *n_region, int inner_block_w, int inner_block_h, int reverse, int upsidedown); -glamor_pixmap_clipped_regions * -glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, - struct pixman_transform *transform, - RegionPtr region, - int *n_region, int dx, int dy, - int repeat_type, int reverse, - int upsidedown); - Bool glamor_composite_largepixmap_region(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, + PixmapPtr source_pixmap, + PixmapPtr mask_pixmap, + PixmapPtr dest_pixmap, RegionPtr region, Bool force_clip, INT16 x_source, INT16 y_source, @@ -867,42 +735,12 @@ Bool glamor_composite_largepixmap_region(CARD8 op, INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height); -Bool glamor_get_transform_block_size(struct pixman_transform *transform, - int block_w, int block_h, - int *transformed_block_w, - int *transformed_block_h); - -void glamor_get_transform_extent_from_box(struct pixman_box32 *temp_box, - struct pixman_transform *transform); - /** * Upload a picture to gl texture. Similar to the * glamor_upload_pixmap_to_texture. Used in rendering. **/ enum glamor_pixmap_status glamor_upload_picture_to_texture(PicturePtr picture); -/** - * Upload bits to a pixmap's texture. This function will - * convert the bits to the specified format/type format - * if the conversion is unavoidable. - **/ -Bool glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, - GLenum type, int no_alpha, int revert, - int swap_rb, void *bits); - -int glamor_create_picture(PicturePtr picture); - -void glamor_set_window_pixmap(WindowPtr pWindow, PixmapPtr pPixmap); - -void glamor_destroy_picture(PicturePtr picture); - -/* fixup a fbo to the exact size as the pixmap. */ -Bool glamor_fixup_pixmap_priv(ScreenPtr screen, - glamor_pixmap_private *pixmap_priv); - -void glamor_picture_format_fixup(PicturePtr picture, - glamor_pixmap_private *pixmap_priv); - void glamor_add_traps(PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntrap, xTrap *traps); @@ -1009,6 +847,22 @@ void glamor_composite_rectangles(CARD8 op, xRenderColor *color, int num_rects, xRectangle *rects); +/* glamor_composite_glyphs.c */ +Bool +glamor_composite_glyphs_init(ScreenPtr pScreen); + +void +glamor_composite_glyphs_fini(ScreenPtr pScreen); + +void +glamor_composite_glyphs(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, + GlyphListPtr list, GlyphPtr *glyphs); + /* glamor_sync.c */ Bool glamor_sync_init(ScreenPtr screen); @@ -1092,8 +946,6 @@ void glamor_xv_render(glamor_port_private *port_priv); #if 0 #define MAX_FBO_SIZE 32 /* For test purpose only. */ #endif -//#define GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK -#define GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK #include "glamor_font.h" diff --git a/xserver/glamor/glamor_program.c b/xserver/glamor/glamor_program.c index 3207aaf15..0a94de62f 100644 --- a/xserver/glamor/glamor_program.c +++ b/xserver/glamor/glamor_program.c @@ -40,14 +40,14 @@ const glamor_facet glamor_fill_solid = { static Bool use_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) { - return glamor_set_tiled(pixmap, gc, prog->fill_offset_uniform, prog->fill_size_uniform); + return glamor_set_tiled(pixmap, gc, prog->fill_offset_uniform, prog->fill_size_inv_uniform); } static const glamor_facet glamor_fill_tile = { .name = "tile", - .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n", + .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", .fs_exec = " gl_FragColor = texture2D(sampler, fill_pos);\n", - .locations = glamor_program_location_fill, + .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos, .use = use_tile, }; @@ -56,17 +56,17 @@ use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) { return glamor_set_stippled(pixmap, gc, prog->fg_uniform, prog->fill_offset_uniform, - prog->fill_size_uniform); + prog->fill_size_inv_uniform); } static const glamor_facet glamor_fill_stipple = { .name = "stipple", - .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n", + .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", .fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n" " if (a == 0.0)\n" " discard;\n" " gl_FragColor = fg;\n"), - .locations = glamor_program_location_fg | glamor_program_location_fill, + .locations = glamor_program_location_fg | glamor_program_location_fillsamp | glamor_program_location_fillpos, .use = use_stipple, }; @@ -81,13 +81,13 @@ use_opaque_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) static const glamor_facet glamor_fill_opaque_stipple = { .name = "opaque_stipple", - .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n", + .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", .fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n" " if (a == 0.0)\n" " gl_FragColor = bg;\n" " else\n" " gl_FragColor = fg;\n"), - .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill, + .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fillsamp | glamor_program_location_fillpos, .use = use_opaque_stipple }; @@ -114,12 +114,15 @@ static glamor_location_var location_vars[] = { .fs_vars = "uniform vec4 bg;\n" }, { - .location = glamor_program_location_fill, + .location = glamor_program_location_fillsamp, + .fs_vars = "uniform sampler2D sampler;\n" + }, + { + .location = glamor_program_location_fillpos, .vs_vars = ("uniform vec2 fill_offset;\n" - "uniform vec2 fill_size;\n" + "uniform vec2 fill_size_inv;\n" "varying vec2 fill_pos;\n"), - .fs_vars = ("uniform sampler2D sampler;\n" - "uniform vec2 fill_size;\n" + .fs_vars = ("uniform vec2 fill_size_inv;\n" "varying vec2 fill_pos;\n") }, { @@ -136,10 +139,12 @@ static glamor_location_var location_vars[] = { .vs_vars = "uniform float dash_length;\n", .fs_vars = "uniform sampler2D dash;\n", }, + { + .location = glamor_program_location_atlas, + .fs_vars = "uniform sampler2D atlas;\n", + }, }; -#define NUM_LOCATION_VARS (sizeof location_vars / sizeof location_vars[0]) - static char * add_var(char *cur, const char *add) { @@ -163,7 +168,7 @@ vs_location_vars(glamor_program_location locations) int l; char *vars = strdup(""); - for (l = 0; vars && l < NUM_LOCATION_VARS; l++) + for (l = 0; vars && l < ARRAY_SIZE(location_vars); l++) if (locations & location_vars[l].location) vars = add_var(vars, location_vars[l].vs_vars); return vars; @@ -175,7 +180,7 @@ fs_location_vars(glamor_program_location locations) int l; char *vars = strdup(""); - for (l = 0; vars && l < NUM_LOCATION_VARS; l++) + for (l = 0; vars && l < ARRAY_SIZE(location_vars); l++) if (locations & location_vars[l].location) vars = add_var(vars, location_vars[l].fs_vars); return vars; @@ -183,6 +188,7 @@ fs_location_vars(glamor_program_location locations) static const char vs_template[] = "%s" /* version */ + "%s" /* defines */ "%s" /* prim vs_vars */ "%s" /* fill vs_vars */ "%s" /* location vs_vars */ @@ -195,12 +201,14 @@ static const char vs_template[] = static const char fs_template[] = "%s" /* version */ GLAMOR_DEFAULT_PRECISION + "%s" /* defines */ "%s" /* prim fs_vars */ "%s" /* fill fs_vars */ "%s" /* location fs_vars */ "void main() {\n" "%s" /* prim fs_exec */ "%s" /* fill fs_exec */ + "%s" /* combine */ "}\n"; static const char * @@ -236,7 +244,9 @@ Bool glamor_build_program(ScreenPtr screen, glamor_program *prog, const glamor_facet *prim, - const glamor_facet *fill) + const glamor_facet *fill, + const char *combine, + const char *defines) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -282,6 +292,7 @@ glamor_build_program(ScreenPtr screen, if (asprintf(&vs_prog_string, vs_template, str(version_string), + str(defines), str(prim->vs_vars), str(fill->vs_vars), vs_vars, @@ -292,26 +303,30 @@ glamor_build_program(ScreenPtr screen, if (asprintf(&fs_prog_string, fs_template, str(version_string), + str(defines), str(prim->fs_vars), str(fill->fs_vars), fs_vars, str(prim->fs_exec), - str(fill->fs_exec)) < 0) + str(fill->fs_exec), + str(combine)) < 0) fs_prog_string = NULL; if (!vs_prog_string || !fs_prog_string) goto fail; + prog->prog = glCreateProgram(); #if DBG - ErrorF("\nPrograms for %s %s\nVertex shader:\n\n%s\n\nFragment Shader:\n\n%s", - prim->name, fill->name, vs_prog_string, fs_prog_string); + ErrorF("\n\tProgram %d for %s %s\n\tVertex shader:\n\n\t================\n%s\n\n\tFragment Shader:\n\n%s\t================\n", + prog->prog, prim->name, fill->name, vs_prog_string, fs_prog_string); #endif - prog->prog = glCreateProgram(); prog->flags = flags; prog->locations = locations; prog->prim_use = prim->use; + prog->prim_use_render = prim->use_render; prog->fill_use = fill->use; + prog->fill_use_render = fill->use_render; vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string); fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string); @@ -329,19 +344,24 @@ glamor_build_program(ScreenPtr screen, #endif glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name); } + if (prog->alpha == glamor_program_alpha_dual_blend) { + glBindFragDataLocationIndexed(prog->prog, 0, 0, "color0"); + glBindFragDataLocationIndexed(prog->prog, 0, 1, "color1"); + } glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name); prog->matrix_uniform = glamor_get_uniform(prog, glamor_program_location_none, "v_matrix"); prog->fg_uniform = glamor_get_uniform(prog, glamor_program_location_fg, "fg"); prog->bg_uniform = glamor_get_uniform(prog, glamor_program_location_bg, "bg"); - prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_offset"); - prog->fill_size_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_size"); + prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_offset"); + prog->fill_size_inv_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_size_inv"); prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font"); prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane"); prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul"); prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash"); prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length"); + prog->atlas_uniform = glamor_get_uniform(prog, glamor_program_location_atlas, "atlas"); free(version_string); free(fs_vars); @@ -396,7 +416,7 @@ glamor_use_program_fill(PixmapPtr pixmap, if (!fill) return NULL; - if (!glamor_build_program(screen, prog, prim, fill)) + if (!glamor_build_program(screen, prog, prim, fill, NULL, NULL)) return NULL; } @@ -405,3 +425,259 @@ glamor_use_program_fill(PixmapPtr pixmap, return prog; } + +static struct blendinfo composite_op_info[] = { + [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, + [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, + [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, + [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, + [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, + [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, + [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, + [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, + [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, +}; + +static void +glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst) +{ + GLenum src_blend, dst_blend; + struct blendinfo *op_info; + + switch (alpha) { + case glamor_program_alpha_ca_first: + op = PictOpOutReverse; + break; + case glamor_program_alpha_ca_second: + op = PictOpAdd; + break; + default: + break; + } + + if (op == PictOpSrc) + return; + + op_info = &composite_op_info[op]; + + src_blend = op_info->source_blend; + dst_blend = op_info->dest_blend; + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (PICT_FORMAT_A(dst->format) == 0 && op_info->dest_alpha) { + if (src_blend == GL_DST_ALPHA) + src_blend = GL_ONE; + else if (src_blend == GL_ONE_MINUS_DST_ALPHA) + src_blend = GL_ZERO; + } + + /* Set up the source alpha value for blending in component alpha mode. */ + if (alpha == glamor_program_alpha_dual_blend) { + switch (dst_blend) { + case GL_SRC_ALPHA: + dst_blend = GL_SRC1_COLOR; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dst_blend = GL_ONE_MINUS_SRC1_COLOR; + break; + } + } else if (alpha != glamor_program_alpha_normal) { + switch (dst_blend) { + case GL_SRC_ALPHA: + dst_blend = GL_SRC_COLOR; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dst_blend = GL_ONE_MINUS_SRC_COLOR; + break; + } + } + + glEnable(GL_BLEND); + glBlendFunc(src_blend, dst_blend); +} + +static Bool +use_source_solid(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) +{ + + glamor_set_blend(op, prog->alpha, dst); + + glamor_set_color_depth(dst->pDrawable->pScreen, 32, + src->pSourcePict->solidFill.color, + prog->fg_uniform); + return TRUE; +} + +static const glamor_facet glamor_source_solid = { + .name = "render_solid", + .fs_exec = " vec4 source = fg;\n", + .locations = glamor_program_location_fg, + .use_render = use_source_solid, +}; + +static Bool +use_source_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) +{ + glamor_set_blend(op, prog->alpha, dst); + + return glamor_set_texture((PixmapPtr) src->pDrawable, + 0, 0, + prog->fill_offset_uniform, + prog->fill_size_inv_uniform); +} + +static const glamor_facet glamor_source_picture = { + .name = "render_picture", + .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", + .fs_exec = " vec4 source = texture2D(sampler, fill_pos);\n", + .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos, + .use_render = use_source_picture, +}; + +static Bool +use_source_1x1_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) +{ + glamor_set_blend(op, prog->alpha, dst); + + return glamor_set_texture_pixmap((PixmapPtr) src->pDrawable); +} + +static const glamor_facet glamor_source_1x1_picture = { + .name = "render_picture", + .fs_exec = " vec4 source = texture2D(sampler, vec2(0.5));\n", + .locations = glamor_program_location_fillsamp, + .use_render = use_source_1x1_picture, +}; + +static const glamor_facet *glamor_facet_source[glamor_program_source_count] = { + [glamor_program_source_solid] = &glamor_source_solid, + [glamor_program_source_picture] = &glamor_source_picture, + [glamor_program_source_1x1_picture] = &glamor_source_1x1_picture, +}; + +static const char *glamor_combine[] = { + [glamor_program_alpha_normal] = " gl_FragColor = source * mask.a;\n", + [glamor_program_alpha_ca_first] = " gl_FragColor = source.a * mask;\n", + [glamor_program_alpha_ca_second] = " gl_FragColor = source * mask;\n", + [glamor_program_alpha_dual_blend] = " color0 = source * mask;\n" + " color1 = source.a * mask;\n" +}; + +static Bool +glamor_setup_one_program_render(ScreenPtr screen, + glamor_program *prog, + glamor_program_source source_type, + glamor_program_alpha alpha, + const glamor_facet *prim, + const char *defines) +{ + if (prog->failed) + return FALSE; + + if (!prog->prog) { + const glamor_facet *fill = glamor_facet_source[source_type]; + + if (!fill) + return FALSE; + + prog->alpha = alpha; + if (!glamor_build_program(screen, prog, prim, fill, glamor_combine[alpha], defines)) + return FALSE; + } + + return TRUE; +} + +glamor_program * +glamor_setup_program_render(CARD8 op, + PicturePtr src, + PicturePtr mask, + PicturePtr dst, + glamor_program_render *program_render, + const glamor_facet *prim, + const char *defines) +{ + ScreenPtr screen = dst->pDrawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_program_alpha alpha; + glamor_program_source source_type; + glamor_program *prog; + + if (op > ARRAY_SIZE(composite_op_info)) + return NULL; + + if (glamor_is_component_alpha(mask)) { + if (glamor_priv->has_dual_blend) { + alpha = glamor_program_alpha_dual_blend; + } else { + /* This only works for PictOpOver */ + if (op != PictOpOver) + return NULL; + + alpha = glamor_program_alpha_ca_first; + } + } else + alpha = glamor_program_alpha_normal; + + if (src->pDrawable) { + + /* Can't do transforms, alphamaps or sourcing from non-pixmaps yet */ + if (src->transform || src->alphaMap || src->pDrawable->type != DRAWABLE_PIXMAP) + return NULL; + + if (src->pDrawable->width == 1 && src->pDrawable->height == 1 && src->repeat) + source_type = glamor_program_source_1x1_picture; + else + source_type = glamor_program_source_picture; + } else { + SourcePictPtr sp = src->pSourcePict; + if (!sp) + return NULL; + switch (sp->type) { + case SourcePictTypeSolidFill: + source_type = glamor_program_source_solid; + break; + default: + return NULL; + } + } + + prog = &program_render->progs[source_type][alpha]; + if (!glamor_setup_one_program_render(screen, prog, source_type, alpha, prim, defines)) + return NULL; + + if (alpha == glamor_program_alpha_ca_first) { + + /* Make sure we can also build the second program before + * deciding to use this path. + */ + if (!glamor_setup_one_program_render(screen, + &program_render->progs[source_type][glamor_program_alpha_ca_second], + source_type, glamor_program_alpha_ca_second, prim, + defines)) + return NULL; + } + return prog; +} + +Bool +glamor_use_program_render(glamor_program *prog, + CARD8 op, + PicturePtr src, + PicturePtr dst) +{ + glUseProgram(prog->prog); + + if (prog->prim_use_render && !prog->prim_use_render(op, src, dst, prog)) + return FALSE; + + if (prog->fill_use_render && !prog->fill_use_render(op, src, dst, prog)) + return FALSE; + return TRUE; +} diff --git a/xserver/glamor/glamor_program.h b/xserver/glamor/glamor_program.h index 56ba03aa8..ab6e46f7b 100644 --- a/xserver/glamor/glamor_program.h +++ b/xserver/glamor/glamor_program.h @@ -27,23 +27,37 @@ typedef enum { glamor_program_location_none = 0, glamor_program_location_fg = 1, glamor_program_location_bg = 2, - glamor_program_location_fill = 4, - glamor_program_location_font = 8, - glamor_program_location_bitplane = 16, - glamor_program_location_dash = 32, + glamor_program_location_fillsamp = 4, + glamor_program_location_fillpos = 8, + glamor_program_location_font = 16, + glamor_program_location_bitplane = 32, + glamor_program_location_dash = 64, + glamor_program_location_atlas = 128, } glamor_program_location; typedef enum { glamor_program_flag_none = 0, } glamor_program_flag; +typedef enum { + glamor_program_alpha_normal, + glamor_program_alpha_ca_first, + glamor_program_alpha_ca_second, + glamor_program_alpha_dual_blend, + glamor_program_alpha_count +} glamor_program_alpha; + typedef struct _glamor_program glamor_program; typedef Bool (*glamor_use) (PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg); +typedef Bool (*glamor_use_render) (CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog); + typedef struct { const char *name; const int version; + char *vs_defines; + char *fs_defines; const char *vs_vars; const char *vs_exec; const char *fs_vars; @@ -52,6 +66,7 @@ typedef struct { const glamor_program_flag flags; const char *source_name; glamor_use use; + glamor_use_render use_render; } glamor_facet; struct _glamor_program { @@ -60,17 +75,21 @@ struct _glamor_program { GLint matrix_uniform; GLint fg_uniform; GLint bg_uniform; - GLint fill_size_uniform; + GLint fill_size_inv_uniform; GLint fill_offset_uniform; GLint font_uniform; GLint bitplane_uniform; GLint bitmul_uniform; GLint dash_uniform; GLint dash_length_uniform; + GLint atlas_uniform; glamor_program_location locations; glamor_program_flag flags; glamor_use prim_use; glamor_use fill_use; + glamor_program_alpha alpha; + glamor_use_render prim_use_render; + glamor_use_render fill_use_render; }; typedef struct { @@ -83,7 +102,9 @@ Bool glamor_build_program(ScreenPtr screen, glamor_program *prog, const glamor_facet *prim, - const glamor_facet *fill); + const glamor_facet *fill, + const char *combine, + const char *defines); Bool glamor_use_program(PixmapPtr pixmap, @@ -97,4 +118,37 @@ glamor_use_program_fill(PixmapPtr pixmap, glamor_program_fill *program_fill, const glamor_facet *prim); +typedef enum { + glamor_program_source_solid, + glamor_program_source_picture, + glamor_program_source_1x1_picture, + glamor_program_source_count, +} glamor_program_source; + +typedef struct { + glamor_program progs[glamor_program_source_count][glamor_program_alpha_count]; +} glamor_program_render; + +static inline Bool +glamor_is_component_alpha(PicturePtr mask) { + if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) + return TRUE; + return FALSE; +} + +glamor_program * +glamor_setup_program_render(CARD8 op, + PicturePtr src, + PicturePtr mask, + PicturePtr dst, + glamor_program_render *program_render, + const glamor_facet *prim, + const char *defines); + +Bool +glamor_use_program_render(glamor_program *prog, + CARD8 op, + PicturePtr src, + PicturePtr dst); + #endif /* _GLAMOR_PROGRAM_H_ */ diff --git a/xserver/glamor/glamor_rects.c b/xserver/glamor/glamor_rects.c index 3a5c3f3f9..e4473209d 100644 --- a/xserver/glamor/glamor_rects.c +++ b/xserver/glamor/glamor_rects.c @@ -51,7 +51,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, int off_x, off_y; GLshort *v; char *vbo_offset; - int box_x, box_y; + int box_index; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -65,7 +65,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, &glamor_facet_polyfillrect_130); if (!prog) - goto bail_ctx; + goto bail; /* Set up the vertex buffers for the points */ @@ -87,7 +87,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, &glamor_facet_polyfillrect_120); if (!prog) - goto bail_ctx; + goto bail; /* Set up the vertex buffers for the points */ @@ -111,11 +111,12 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); - glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); + glamor_set_destination_drawable(drawable, box_index, TRUE, FALSE, + prog->matrix_uniform, &off_x, &off_y); while (nbox--) { glScissor(box->x1 + off_x, @@ -126,27 +127,17 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable, if (glamor_priv->glsl_version >= 130) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect); else { - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - glDrawArrays(GL_QUADS, 0, nrect * 4); - } else { - int i; - for (i = 0; i < nrect; i++) { - glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); - } - } + glamor_glDrawArrays_GL_QUADS(glamor_priv, nrect); } } } glDisable(GL_SCISSOR_TEST); - glDisable(GL_COLOR_LOGIC_OP); if (glamor_priv->glsl_version >= 130) glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); return TRUE; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } @@ -173,15 +164,3 @@ glamor_poly_fill_rect(DrawablePtr drawable, return; glamor_poly_fill_rect_bail(drawable, gc, nrect, prect); } - -Bool -glamor_poly_fill_rect_nf(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect) -{ - if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect)) - return TRUE; - if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) - return FALSE; - glamor_poly_fill_rect_bail(drawable, gc, nrect, prect); - return TRUE; -} diff --git a/xserver/glamor/glamor_render.c b/xserver/glamor/glamor_render.c index d9b16ea05..73ac831ee 100644 --- a/xserver/glamor/glamor_render.c +++ b/xserver/glamor/glamor_render.c @@ -34,7 +34,6 @@ #include "glamor_priv.h" -#ifdef RENDER #include "mipict.h" #include "fbpict.h" #if 0 @@ -73,146 +72,153 @@ glamor_create_composite_fs(struct shader_key *key) "uniform int source_repeat_mode;\n" "uniform int mask_repeat_mode;\n"; const char *relocate_texture = - GLAMOR_DEFAULT_PRECISION "vec2 rel_tex_coord(vec2 texture, vec4 wh, int repeat) \n" "{\n" - " vec2 rel_tex; \n" - " rel_tex = texture * wh.xy; \n" - " if (repeat == RepeatNone)\n" + " vec2 rel_tex; \n" + " rel_tex = texture * wh.xy; \n" + " if (repeat == RepeatFix + RepeatNone)\n" " return rel_tex; \n" - " else if (repeat == RepeatNormal) \n" - " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh.xy); \n" - " else if(repeat == RepeatPad) { \n" - " if (rel_tex.x >= 1.0) rel_tex.x = 1.0 - wh.z * wh.x / 2.; \n" - " else if(rel_tex.x < 0.0) rel_tex.x = 0.0; \n" - " if (rel_tex.y >= 1.0) rel_tex.y = 1.0 - wh.w * wh.y / 2.; \n" - " else if(rel_tex.y < 0.0) rel_tex.y = 0.0; \n" - " rel_tex = rel_tex / wh.xy; \n" - " } \n" - " else if(repeat == RepeatReflect) {\n" + " else if (repeat == RepeatFix + RepeatNormal) \n" + " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh.xy); \n" + " else if (repeat == RepeatFix + RepeatPad) { \n" + " if (rel_tex.x >= 1.0) \n" + " rel_tex.x = 1.0 - wh.z * wh.x / 2.; \n" + " else if (rel_tex.x < 0.0) \n" + " rel_tex.x = 0.0; \n" + " if (rel_tex.y >= 1.0) \n" + " rel_tex.y = 1.0 - wh.w * wh.y / 2.; \n" + " else if (rel_tex.y < 0.0) \n" + " rel_tex.y = 0.0; \n" + " rel_tex = rel_tex / wh.xy; \n" + " } else if (repeat == RepeatFix + RepeatReflect) {\n" " if ((1.0 - mod(abs(floor(rel_tex.x)), 2.0)) < 0.001)\n" - " rel_tex.x = 2.0 - (1.0 - fract(rel_tex.x))/wh.x;\n" + " rel_tex.x = 2.0 - (1.0 - fract(rel_tex.x)) / wh.x;\n" " else \n" - " rel_tex.x = fract(rel_tex.x)/wh.x;\n" + " rel_tex.x = fract(rel_tex.x) / wh.x;\n" " if ((1.0 - mod(abs(floor(rel_tex.y)), 2.0)) < 0.001)\n" - " rel_tex.y = 2.0 - (1.0 - fract(rel_tex.y))/wh.y;\n" + " rel_tex.y = 2.0 - (1.0 - fract(rel_tex.y)) / wh.y;\n" " else \n" - " rel_tex.y = fract(rel_tex.y)/wh.y;\n" - " } \n" - " return rel_tex; \n" + " rel_tex.y = fract(rel_tex.y) / wh.y;\n" + " } \n" + " return rel_tex; \n" "}\n"; /* The texture and the pixmap size is not match eaxctly, so can't sample it directly. * rel_sampler will recalculate the texture coords.*/ const char *rel_sampler = - " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec4 wh, int repeat, int set_alpha)\n" + " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec4 wh, int repeat)\n" "{\n" - " tex = rel_tex_coord(tex, wh, repeat - RepeatFix);\n" - " if (repeat == RepeatFix) {\n" - " if (!(tex.x >= 0.0 && tex.x < 1.0 \n" - " && tex.y >= 0.0 && tex.y < 1.0))\n" - " return vec4(0.0, 0.0, 0.0, set_alpha);\n" - " tex = (fract(tex) / wh.xy);\n" + " if (repeat >= RepeatFix) {\n" + " tex = rel_tex_coord(tex, wh, repeat);\n" + " if (repeat == RepeatFix + RepeatNone) {\n" + " if (tex.x < 0.0 || tex.x >= 1.0 || \n" + " tex.y < 0.0 || tex.y >= 1.0)\n" + " return vec4(0.0, 0.0, 0.0, 0.0);\n" + " tex = (fract(tex) / wh.xy);\n" + " }\n" " }\n" - " if (set_alpha != 1)\n" - " return texture2D(tex_image, tex);\n" - " else\n" - " return vec4(texture2D(tex_image, tex).rgb, 1.0);\n" + " return texture2D(tex_image, tex);\n" "}\n"; const char *source_solid_fetch = - GLAMOR_DEFAULT_PRECISION "uniform vec4 source;\n" "vec4 get_source()\n" "{\n" " return source;\n" "}\n"; const char *source_alpha_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" "uniform vec4 source_wh;" "vec4 get_source()\n" "{\n" - " if (source_repeat_mode < RepeatFix)\n" - " return texture2D(source_sampler, source_texture);\n" - " else \n" - " return rel_sampler(source_sampler, source_texture,\n" - " source_wh, source_repeat_mode, 0);\n" + " return rel_sampler(source_sampler, source_texture,\n" + " source_wh, source_repeat_mode);\n" "}\n"; const char *source_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" "uniform vec4 source_wh;\n" "vec4 get_source()\n" "{\n" - " if (source_repeat_mode < RepeatFix) \n" - " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" - " else \n" - " return rel_sampler(source_sampler, source_texture,\n" - " source_wh, source_repeat_mode, 1);\n" + " return vec4(rel_sampler(source_sampler, source_texture,\n" + " source_wh, source_repeat_mode).rgb,\n" + " 1.0);\n" + "}\n"; + const char *mask_none = + "vec4 get_mask()\n" + "{\n" + " return vec4(0.0, 0.0, 0.0, 1.0);\n" "}\n"; const char *mask_solid_fetch = - GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" "vec4 get_mask()\n" "{\n" " return mask;\n" "}\n"; const char *mask_alpha_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" "uniform vec4 mask_wh;\n" "vec4 get_mask()\n" "{\n" - " if (mask_repeat_mode < RepeatFix) \n" - " return texture2D(mask_sampler, mask_texture);\n" - " else \n" - " return rel_sampler(mask_sampler, mask_texture,\n" - " mask_wh, mask_repeat_mode, 0);\n" + " return rel_sampler(mask_sampler, mask_texture,\n" + " mask_wh, mask_repeat_mode);\n" "}\n"; const char *mask_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" "uniform vec4 mask_wh;\n" "vec4 get_mask()\n" "{\n" - " if (mask_repeat_mode < RepeatFix) \n" - " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" - " else \n" - " return rel_sampler(mask_sampler, mask_texture,\n" - " mask_wh, mask_repeat_mode, 1);\n" - "}\n"; - const char *in_source_only = - GLAMOR_DEFAULT_PRECISION - "void main()\n" - "{\n" - " gl_FragColor = get_source();\n" + " return vec4(rel_sampler(mask_sampler, mask_texture,\n" + " mask_wh, mask_repeat_mode).rgb, 1.0);\n" "}\n"; + + const char *dest_swizzle_default = + "vec4 dest_swizzle(vec4 color)\n" + "{" + " return color;" + "}"; + const char *dest_swizzle_alpha_to_red = + "vec4 dest_swizzle(vec4 color)\n" + "{" + " float undef;\n" + " return vec4(color.a, undef, undef, undef);" + "}"; + const char *in_normal = - GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" - " gl_FragColor = get_source() * get_mask().a;\n" + " gl_FragColor = dest_swizzle(get_source() * get_mask().a);\n" "}\n"; const char *in_ca_source = - GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" - " gl_FragColor = get_source() * get_mask();\n" + " gl_FragColor = dest_swizzle(get_source() * get_mask());\n" "}\n"; const char *in_ca_alpha = - GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" - " gl_FragColor = get_source().a * get_mask();\n" + " gl_FragColor = dest_swizzle(get_source().a * get_mask());\n" "}\n"; + const char *in_ca_dual_blend = + "out vec4 color0;\n" + "out vec4 color1;\n" + "void main()\n" + "{\n" + " color0 = dest_swizzle(get_source() * get_mask());\n" + " color1 = dest_swizzle(get_source().a * get_mask());\n" + "}\n"; + const char *header_ca_dual_blend = + "#version 130\n"; + char *source; const char *source_fetch; const char *mask_fetch = ""; const char *in; + const char *header; + const char *header_norm = ""; + const char *dest_swizzle; GLuint prog; switch (key->source) { @@ -231,6 +237,7 @@ glamor_create_composite_fs(struct shader_key *key) switch (key->mask) { case SHADER_MASK_NONE: + mask_fetch = mask_none; break; case SHADER_MASK_SOLID: mask_fetch = mask_solid_fetch; @@ -245,25 +252,45 @@ glamor_create_composite_fs(struct shader_key *key) FatalError("Bad composite shader mask"); } - switch (key->in) { - case SHADER_IN_SOURCE_ONLY: - in = in_source_only; + /* If we're storing to an a8 texture but our texture format is + * GL_RED because of a core context, then we need to make sure to + * put the alpha into the red channel. + */ + switch (key->dest_swizzle) { + case SHADER_DEST_SWIZZLE_DEFAULT: + dest_swizzle = dest_swizzle_default; + break; + case SHADER_DEST_SWIZZLE_ALPHA_TO_RED: + dest_swizzle = dest_swizzle_alpha_to_red; break; - case SHADER_IN_NORMAL: + default: + FatalError("Bad composite shader dest swizzle"); + } + + header = header_norm; + switch (key->in) { + case glamor_program_alpha_normal: in = in_normal; break; - case SHADER_IN_CA_SOURCE: + case glamor_program_alpha_ca_first: in = in_ca_source; break; - case SHADER_IN_CA_ALPHA: + case glamor_program_alpha_ca_second: in = in_ca_alpha; break; + case glamor_program_alpha_dual_blend: + in = in_ca_dual_blend; + header = header_ca_dual_blend; + break; default: FatalError("Bad composite IN type"); } - XNFasprintf(&source, "%s%s%s%s%s%s", repeat_define, relocate_texture, - rel_sampler, source_fetch, mask_fetch, in); + XNFasprintf(&source, + "%s" + GLAMOR_DEFAULT_PRECISION + "%s%s%s%s%s%s%s", header, repeat_define, relocate_texture, + rel_sampler, source_fetch, mask_fetch, dest_swizzle, in); prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source); free(source); @@ -332,6 +359,10 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1"); + if (key->in == glamor_program_alpha_dual_blend) { + glBindFragDataLocationIndexed(prog, 0, 0, "color0"); + glBindFragDataLocationIndexed(prog, 0, 1, "color1"); + } glamor_link_glsl_prog(screen, prog, "composite"); shader->prog = prog; @@ -373,73 +404,36 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_composite_shader *shader; - shader = &glamor_priv->composite_shader[key->source][key->mask][key->in]; + shader = &glamor_priv->composite_shader[key->source][key->mask][key->in][key->dest_swizzle]; if (shader->prog == 0) glamor_create_composite_shader(screen, key, shader); return shader; } -static void -glamor_init_eb(unsigned short *eb, int vert_cnt) +static GLenum +glamor_translate_blend_alpha_to_red(GLenum blend) { - int i, j; - - for (i = 0, j = 0; j < vert_cnt; i += 6, j += 4) { - eb[i] = j; - eb[i + 1] = j + 1; - eb[i + 2] = j + 2; - eb[i + 3] = j; - eb[i + 4] = j + 2; - eb[i + 5] = j + 3; + switch (blend) { + case GL_SRC_ALPHA: + return GL_SRC_COLOR; + case GL_DST_ALPHA: + return GL_DST_COLOR; + case GL_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_COLOR; + case GL_ONE_MINUS_DST_ALPHA: + return GL_ONE_MINUS_DST_COLOR; + default: + return blend; } } -void -glamor_init_composite_shaders(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv; - unsigned short *eb; - int eb_size; - - glamor_priv = glamor_get_screen_private(screen); - glamor_make_current(glamor_priv); - glGenBuffers(1, &glamor_priv->ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); - - eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2; - - eb = XNFalloc(eb_size); - glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW); - free(eb); -} - -void -glamor_fini_composite_shaders(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv; - glamor_composite_shader *shader; - int i, j, k; - - glamor_priv = glamor_get_screen_private(screen); - glamor_make_current(glamor_priv); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &glamor_priv->ebo); - - for (i = 0; i < SHADER_SOURCE_COUNT; i++) - for (j = 0; j < SHADER_MASK_COUNT; j++) - for (k = 0; k < SHADER_IN_COUNT; k++) { - shader = &glamor_priv->composite_shader[i][j][k]; - if (shader->prog) - glDeleteProgram(shader->prog); - } -} - static Bool glamor_set_composite_op(ScreenPtr screen, CARD8 op, struct blendinfo *op_info_result, - PicturePtr dest, PicturePtr mask) + PicturePtr dest, PicturePtr mask, + enum ca_state ca_state, + struct shader_key *key) { GLenum source_blend, dest_blend; struct blendinfo *op_info; @@ -448,6 +442,7 @@ glamor_set_composite_op(ScreenPtr screen, glamor_fallback("unsupported render op %d \n", op); return GL_FALSE; } + op_info = &composite_op_info[op]; source_blend = op_info->source_blend; @@ -464,12 +459,33 @@ glamor_set_composite_op(ScreenPtr screen, } /* Set up the source alpha value for blending in component alpha mode. */ - if (mask && mask->componentAlpha - && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) { - if (dest_blend == GL_SRC_ALPHA) + if (ca_state == CA_DUAL_BLEND) { + switch (dest_blend) { + case GL_SRC_ALPHA: + dest_blend = GL_SRC1_COLOR; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dest_blend = GL_ONE_MINUS_SRC1_COLOR; + break; + } + } else if (mask && mask->componentAlpha + && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) { + switch (dest_blend) { + case GL_SRC_ALPHA: dest_blend = GL_SRC_COLOR; - else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA) + break; + case GL_ONE_MINUS_SRC_ALPHA: dest_blend = GL_ONE_MINUS_SRC_COLOR; + break; + } + } + + /* If we're outputting our alpha to the red channel, then any + * reads of alpha for blending need to come from the red channel. + */ + if (key->dest_swizzle == SHADER_DEST_SWIZZLE_ALPHA_TO_RED) { + source_blend = glamor_translate_blend_alpha_to_red(source_blend); + dest_blend = glamor_translate_blend_alpha_to_red(dest_blend); } op_info_result->source_blend = source_blend; @@ -483,15 +499,16 @@ glamor_set_composite_op(ScreenPtr screen, static void glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, PicturePtr picture, - glamor_pixmap_private *pixmap_priv, + PixmapPtr pixmap, GLuint wh_location, GLuint repeat_location) { + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); float wh[4]; int repeat_type; glamor_make_current(glamor_priv); glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex); + glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); repeat_type = picture->repeatType; switch (picture->repeatType) { case RepeatNone: @@ -539,23 +556,15 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, * GLES2 doesn't support RepeatNone. We need to fix it anyway. * **/ - if (repeat_type != RepeatNone) + if (glamor_pixmap_priv_is_large(pixmap_priv) || + (glamor_priv->gl_flavor == GLAMOR_GL_ES2 && repeat_type == RepeatNone && + picture->transform)) { + glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap, pixmap_priv); + glUniform4fv(wh_location, 1, wh); + repeat_type += RepeatFix; - else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - if (picture->transform - || (GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv))) - repeat_type += RepeatFix; - } - if (repeat_type >= RepeatFix) { - glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); - if ((wh[0] != 1.0 || wh[1] != 1.0) - || (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && repeat_type == RepeatFix)) - glUniform4fv(wh_location, 1, wh); - else - repeat_type -= RepeatFix; } + glUniform1i(repeat_location, repeat_type); } @@ -565,33 +574,6 @@ glamor_set_composite_solid(float *color, GLint uniform_location) glUniform4fv(uniform_location, 1, color); } -static int -compatible_formats(CARD8 op, PicturePtr dst, PicturePtr src) -{ - if (op == PictOpSrc) { - if (src->format == dst->format) - return 1; - - if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8) - return 1; - - if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8) - return 1; - } - else if (op == PictOpOver) { - if (src->alphaMap || dst->alphaMap) - return 0; - - if (src->format != dst->format) - return 0; - - if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8) - return 1; - } - - return 0; -} - static char glamor_get_picture_location(PicturePtr picture) { @@ -613,55 +595,7 @@ glamor_get_picture_location(PicturePtr picture) return glamor_get_drawable_location(picture->pDrawable); } -static Bool -glamor_composite_with_copy(CARD8 op, - PicturePtr source, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_dest, INT16 y_dest, RegionPtr region) -{ - int ret = FALSE; - - if (!source->pDrawable) - return FALSE; - - if (!compatible_formats(op, dest, source)) - return FALSE; - - if (source->repeat || source->transform) { - return FALSE; - } - - x_dest += dest->pDrawable->x; - y_dest += dest->pDrawable->y; - x_source += source->pDrawable->x; - y_source += source->pDrawable->y; - if (PICT_FORMAT_A(source->format) == 0) { - /* Fallback if we sample outside the source so that we - * swizzle the correct clear color for out-of-bounds texels. - */ - if (region->extents.x1 + x_source - x_dest < 0) - goto cleanup_region; - if (region->extents.x2 + x_source - x_dest > source->pDrawable->width) - goto cleanup_region; - - if (region->extents.y1 + y_source - y_dest < 0) - goto cleanup_region; - if (region->extents.y2 + y_source - y_dest > source->pDrawable->height) - goto cleanup_region; - } - glamor_copy(source->pDrawable, - dest->pDrawable, NULL, - RegionRects(region), RegionNumRects(region), - x_source - x_dest, y_source - y_dest, - FALSE, FALSE, 0, NULL); - ret = TRUE; - cleanup_region: - return ret; -} - -void * +static void * glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -669,7 +603,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) char *vbo_offset; float *vb; - glamor_priv->render_nr_verts = 0; + glamor_priv->render_nr_quads = 0; glamor_priv->vb_stride = 2 * sizeof(float); if (glamor_priv->has_source_coords) glamor_priv->vb_stride += 2 * sizeof(float); @@ -711,27 +645,20 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_make_current(glamor_priv); - if (!glamor_priv->render_nr_verts) + if (!glamor_priv->render_nr_quads) return; - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts, - (glamor_priv->render_nr_verts * 3) / 2, - GL_UNSIGNED_SHORT, NULL); - } else { - glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, - GL_UNSIGNED_SHORT, NULL); - } + glamor_glDrawArrays_GL_QUADS(glamor_priv, glamor_priv->render_nr_quads); } -int pict_format_combine_tab[][3] = { +static const int pict_format_combine_tab[][3] = { {PICT_TYPE_ARGB, PICT_TYPE_A, PICT_TYPE_ARGB}, {PICT_TYPE_ABGR, PICT_TYPE_A, PICT_TYPE_ABGR}, }; static Bool combine_pict_format(PictFormatShort * des, const PictFormatShort src, - const PictFormatShort mask, enum shader_in in_ca) + const PictFormatShort mask, glamor_program_alpha in_ca) { PictFormatShort new_vis; int src_type, mask_type, src_bpp; @@ -748,20 +675,22 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src, new_vis = PICT_FORMAT_VIS(src) | PICT_FORMAT_VIS(mask); switch (in_ca) { - case SHADER_IN_SOURCE_ONLY: - return TRUE; - case SHADER_IN_NORMAL: + case glamor_program_alpha_normal: src_type = PICT_FORMAT_TYPE(src); mask_type = PICT_TYPE_A; break; - case SHADER_IN_CA_SOURCE: + case glamor_program_alpha_ca_first: src_type = PICT_FORMAT_TYPE(src); mask_type = PICT_FORMAT_TYPE(mask); break; - case SHADER_IN_CA_ALPHA: + case glamor_program_alpha_ca_second: src_type = PICT_TYPE_A; mask_type = PICT_FORMAT_TYPE(mask); break; + case glamor_program_alpha_dual_blend: + src_type = PICT_FORMAT_TYPE(src); + mask_type = PICT_FORMAT_TYPE(mask); + break; default: return FALSE; } @@ -771,10 +700,7 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src, return TRUE; } - for (i = 0; - i < - sizeof(pict_format_combine_tab) / - sizeof(pict_format_combine_tab[0]); i++) { + for (i = 0; i < ARRAY_SIZE(pict_format_combine_tab); i++) { if ((src_type == pict_format_combine_tab[i][0] && mask_type == pict_format_combine_tab[i][1]) || (src_type == pict_format_combine_tab[i][1] @@ -788,7 +714,8 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src, } static void -glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, +glamor_set_normalize_tcoords_generic(PixmapPtr pixmap, + glamor_pixmap_private *priv, int repeat_type, float *matrix, float xscale, float yscale, @@ -806,36 +733,61 @@ glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, x2, y2, texcoords, stride); else if (!matrix && repeat_type != RepeatNone) - glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, + glamor_set_repeat_normalize_tcoords_ext(pixmap, priv, repeat_type, xscale, yscale, x1, y1, x2, y2, texcoords, stride); else if (matrix && repeat_type != RepeatNone) - glamor_set_repeat_transformed_normalize_tcoords_ext(priv, repeat_type, + glamor_set_repeat_transformed_normalize_tcoords_ext(pixmap, priv, repeat_type, matrix, xscale, yscale, x1, y1, x2, y2, texcoords, stride); } -Bool +/** + * Returns whether the general composite path supports this picture + * format for a pixmap that is permanently stored in an FBO (as + * opposed to the GLAMOR_PIXMAP_DYNAMIC_UPLOAD path). + * + * We could support many more formats by using GL_ARB_texture_view to + * parse the same bits as different formats. For now, we only support + * tweaking whether we sample the alpha bits of an a8r8g8b8, or just + * force them to 1. + */ +static Bool +glamor_render_format_is_supported(PictFormatShort format) +{ + switch (format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + case PICT_a8: + return TRUE; + default: + return FALSE; + } +} + +static Bool glamor_composite_choose_shader(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, + PixmapPtr source_pixmap, + PixmapPtr mask_pixmap, + PixmapPtr dest_pixmap, glamor_pixmap_private *source_pixmap_priv, glamor_pixmap_private *mask_pixmap_priv, glamor_pixmap_private *dest_pixmap_priv, struct shader_key *s_key, glamor_composite_shader ** shader, struct blendinfo *op_info, - PictFormatShort *psaved_source_format) + PictFormatShort *psaved_source_format, + enum ca_state ca_state) { ScreenPtr screen = dest->pDrawable->pScreen; - PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; - PixmapPtr source_pixmap = NULL; - PixmapPtr mask_pixmap = NULL; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); enum glamor_pixmap_status source_status = GLAMOR_NONE; enum glamor_pixmap_status mask_status = GLAMOR_NONE; PictFormatShort saved_source_format = 0; @@ -849,6 +801,11 @@ glamor_composite_choose_shader(CARD8 op, goto fail; } + if (!glamor_render_format_is_supported(dest->format)) { + glamor_fallback("Unsupported dest picture format.\n"); + goto fail; + } + memset(&key, 0, sizeof(key)); if (!source) { key.source = SHADER_SOURCE_SOLID; @@ -894,17 +851,19 @@ glamor_composite_choose_shader(CARD8 op, } if (!mask->componentAlpha) { - key.in = SHADER_IN_NORMAL; + key.in = glamor_program_alpha_normal; } else { if (op == PictOpClear) key.mask = SHADER_MASK_NONE; + else if (glamor_priv->has_dual_blend) + key.in = glamor_program_alpha_dual_blend; else if (op == PictOpSrc || op == PictOpAdd || op == PictOpIn || op == PictOpOut || op == PictOpOverReverse) - key.in = SHADER_IN_CA_SOURCE; + key.in = glamor_program_alpha_ca_second; else if (op == PictOpOutReverse || op == PictOpInReverse) { - key.in = SHADER_IN_CA_ALPHA; + key.in = glamor_program_alpha_ca_first; } else { glamor_fallback("Unsupported component alpha op: %d\n", op); @@ -914,7 +873,13 @@ glamor_composite_choose_shader(CARD8 op, } else { key.mask = SHADER_MASK_NONE; - key.in = SHADER_IN_SOURCE_ONLY; + } + + if (dest_pixmap->drawable.bitsPerPixel <= 8 && + glamor_priv->one_channel_format == GL_RED) { + key.dest_swizzle = SHADER_DEST_SWIZZLE_ALPHA_TO_RED; + } else { + key.dest_swizzle = SHADER_DEST_SWIZZLE_DEFAULT; } if (source && source->alphaMap) { @@ -928,13 +893,12 @@ glamor_composite_choose_shader(CARD8 op, if (key.source == SHADER_SOURCE_TEXTURE || key.source == SHADER_SOURCE_TEXTURE_ALPHA) { - source_pixmap = source_pixmap_priv->base.pixmap; if (source_pixmap == dest_pixmap) { /* XXX source and the dest share the same texture. * Does it need special handle? */ glamor_fallback("source == dest\n"); } - if (source_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) { + if (source_pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD source_status = GLAMOR_UPLOAD_PENDING; #else @@ -946,12 +910,11 @@ glamor_composite_choose_shader(CARD8 op, if (key.mask == SHADER_MASK_TEXTURE || key.mask == SHADER_MASK_TEXTURE_ALPHA) { - mask_pixmap = mask_pixmap_priv->base.pixmap; if (mask_pixmap == dest_pixmap) { glamor_fallback("mask == dest\n"); goto fail; } - if (mask_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) { + if (mask_pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD mask_status = GLAMOR_UPLOAD_PENDING; #else @@ -976,9 +939,6 @@ glamor_composite_choose_shader(CARD8 op, goto fail; } - if (source->format != saved_source_format) { - glamor_picture_format_fixup(source, source_pixmap_priv); - } /* XXX * By default, glamor_upload_picture_to_texture will wire alpha to 1 * if one picture doesn't have alpha. So we don't do that again in @@ -1019,6 +979,11 @@ glamor_composite_choose_shader(CARD8 op, glamor_fallback("Failed to upload source texture.\n"); goto fail; } + } else { + if (!glamor_render_format_is_supported(source->format)) { + glamor_fallback("Unsupported source picture format.\n"); + goto fail; + } } if (mask_status == GLAMOR_UPLOAD_PENDING) { @@ -1027,6 +992,11 @@ glamor_composite_choose_shader(CARD8 op, glamor_fallback("Failed to upload mask texture.\n"); goto fail; } + } else if (mask) { + if (!glamor_render_format_is_supported(mask->format)) { + glamor_fallback("Unsupported mask picture format.\n"); + goto fail; + } } } #endif @@ -1041,25 +1011,10 @@ glamor_composite_choose_shader(CARD8 op, goto fail; } - /*Before enter the rendering stage, we need to fixup - * transformed source and mask, if the transform is not int translate. */ - if (key.source != SHADER_SOURCE_SOLID - && source->transform - && !pixman_transform_is_int_translate(source->transform) - && source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { - if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv)) - goto fail; - } - if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID - && mask->transform - && !pixman_transform_is_int_translate(mask->transform) - && mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { - if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv)) - goto fail; - } - - if (!glamor_set_composite_op(screen, op, op_info, dest, mask)) + if (!glamor_set_composite_op(screen, op, op_info, dest, mask, ca_state, + &key)) { goto fail; + } *shader = glamor_lookup_composite_shader(screen, &key); if ((*shader)->prog == 0) { @@ -1071,7 +1026,7 @@ glamor_composite_choose_shader(CARD8 op, memcpy(&(*shader)->source_solid_color[0], source_solid_color, 4 * sizeof(float)); else { - (*shader)->source_priv = source_pixmap_priv; + (*shader)->source_pixmap = source_pixmap; (*shader)->source = source; } @@ -1079,7 +1034,7 @@ glamor_composite_choose_shader(CARD8 op, memcpy(&(*shader)->mask_solid_color[0], mask_solid_color, 4 * sizeof(float)); else { - (*shader)->mask_priv = mask_pixmap_priv; + (*shader)->mask_pixmap = mask_pixmap; (*shader)->mask = mask; } @@ -1095,16 +1050,13 @@ glamor_composite_choose_shader(CARD8 op, return ret; } -void -glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, +static void +glamor_composite_set_shader_blend(glamor_screen_private *glamor_priv, + glamor_pixmap_private *dest_priv, struct shader_key *key, glamor_composite_shader *shader, struct blendinfo *op_info) { - glamor_screen_private *glamor_priv; - - glamor_priv = dest_priv->base.glamor_priv; - glamor_make_current(glamor_priv); glUseProgram(shader->prog); @@ -1115,7 +1067,7 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, else { glamor_set_composite_texture(glamor_priv, 0, shader->source, - shader->source_priv, shader->source_wh, + shader->source_pixmap, shader->source_wh, shader->source_repeat_mode); } @@ -1127,7 +1079,7 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, else { glamor_set_composite_texture(glamor_priv, 1, shader->mask, - shader->mask_priv, shader->mask_wh, + shader->mask_pixmap, shader->mask_wh, shader->mask_repeat_mode); } } @@ -1146,17 +1098,17 @@ glamor_composite_with_shader(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, + PixmapPtr source_pixmap, + PixmapPtr mask_pixmap, + PixmapPtr dest_pixmap, glamor_pixmap_private *source_pixmap_priv, glamor_pixmap_private *mask_pixmap_priv, glamor_pixmap_private *dest_pixmap_priv, int nrect, glamor_composite_rect_t *rects, - Bool two_pass_ca) + enum ca_state ca_state) { ScreenPtr screen = dest->pDrawable->pScreen; - glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; - PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; - PixmapPtr source_pixmap = NULL; - PixmapPtr mask_pixmap = NULL; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); GLfloat dst_xscale, dst_yscale; GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; struct shader_key key, key_ca; @@ -1172,26 +1124,29 @@ glamor_composite_with_shader(CARD8 op, struct blendinfo op_info, op_info_ca; if (!glamor_composite_choose_shader(op, source, mask, dest, + source_pixmap, mask_pixmap, dest_pixmap, source_pixmap_priv, mask_pixmap_priv, dest_pixmap_priv, &key, &shader, &op_info, - &saved_source_format)) { + &saved_source_format, ca_state)) { glamor_fallback("glamor_composite_choose_shader failed\n"); return ret; } - if (two_pass_ca) { + if (ca_state == CA_TWO_PASS) { if (!glamor_composite_choose_shader(PictOpAdd, source, mask, dest, + source_pixmap, mask_pixmap, dest_pixmap, source_pixmap_priv, mask_pixmap_priv, dest_pixmap_priv, &key_ca, &shader_ca, &op_info_ca, - &saved_source_format)) { + &saved_source_format, ca_state)) { glamor_fallback("glamor_composite_choose_shader failed\n"); return ret; } } - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); - glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info); + glamor_set_destination_pixmap_priv_nc(glamor_priv, dest_pixmap, dest_pixmap_priv); + glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, &key, shader, &op_info); + glamor_set_alu(screen, GXcopy); glamor_make_current(glamor_priv); @@ -1203,10 +1158,9 @@ glamor_composite_with_shader(CARD8 op, dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, &dest_x_off, &dest_y_off); - pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_dest_scale(dest_pixmap, dest_pixmap_priv, &dst_xscale, &dst_yscale); if (glamor_priv->has_source_coords) { - source_pixmap = source_pixmap_priv->base.pixmap; glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &source_x_off, &source_y_off); pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); @@ -1217,7 +1171,6 @@ glamor_composite_with_shader(CARD8 op, } if (glamor_priv->has_mask_coords) { - mask_pixmap = mask_pixmap_priv->base.pixmap; glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &mask_x_off, &mask_y_off); pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); @@ -1269,7 +1222,8 @@ glamor_composite_with_shader(CARD8 op, vb_stride); vertices += 2; if (key.source != SHADER_SOURCE_SOLID) { - glamor_set_normalize_tcoords_generic(source_pixmap_priv, + glamor_set_normalize_tcoords_generic(source_pixmap, + source_pixmap_priv, source->repeatType, psrc_matrix, src_xscale, src_yscale, x_source, @@ -1280,7 +1234,8 @@ glamor_composite_with_shader(CARD8 op, } if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { - glamor_set_normalize_tcoords_generic(mask_pixmap_priv, + glamor_set_normalize_tcoords_generic(mask_pixmap, + mask_pixmap_priv, mask->repeatType, pmask_matrix, mask_xscale, mask_yscale, x_mask, @@ -1289,7 +1244,7 @@ glamor_composite_with_shader(CARD8 op, vertices, vb_stride); vertices += 2; } - glamor_priv->render_nr_verts += 4; + glamor_priv->render_nr_quads++; rects++; /* We've incremented by one of our 4 verts, now do the other 3. */ @@ -1298,12 +1253,12 @@ glamor_composite_with_shader(CARD8 op, glamor_put_vbo_space(screen); glamor_flush_composite_rects(screen); nrect -= rect_processed; - if (two_pass_ca) { - glamor_composite_set_shader_blend(dest_pixmap_priv, + if (ca_state == CA_TWO_PASS) { + glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, &key_ca, shader_ca, &op_info_ca); glamor_flush_composite_rects(screen); if (nrect) - glamor_composite_set_shader_blend(dest_pixmap_priv, + glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, &key, shader, &op_info); } } @@ -1320,7 +1275,7 @@ glamor_composite_with_shader(CARD8 op, return ret; } -PicturePtr +static PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, PicturePtr source, int x_source, @@ -1329,12 +1284,17 @@ glamor_convert_gradient_picture(ScreenPtr screen, PixmapPtr pixmap; PicturePtr dst = NULL; int error; + PictFormatPtr pFormat; PictFormatShort format; - if (!source->pDrawable) + if (source->pDrawable) { + pFormat = source->pFormat; + format = pFormat->format; + } else { format = PICT_a8r8g8b8; - else - format = source->format; + pFormat = PictureMatchFormat(screen, 32, format); + } + #ifdef GLAMOR_GRADIENT_SHADER if (!source->pDrawable) { if (source->pSourcePict->type == SourcePictTypeLinear) { @@ -1370,10 +1330,7 @@ glamor_convert_gradient_picture(ScreenPtr screen, return NULL; dst = CreatePicture(0, - &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), - format), 0, 0, serverClient, &error); + &pixmap->drawable, pFormat, 0, 0, serverClient, &error); glamor_destroy_pixmap(pixmap); if (!dst) return NULL; @@ -1390,18 +1347,22 @@ glamor_composite_clipped_region(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, + PixmapPtr source_pixmap, + PixmapPtr mask_pixmap, + PixmapPtr dest_pixmap, RegionPtr region, int x_source, int y_source, int x_mask, int y_mask, int x_dest, int y_dest) { + glamor_pixmap_private *source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + glamor_pixmap_private *mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + glamor_pixmap_private *dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + glamor_screen_private *glamor_priv = glamor_get_screen_private(dest_pixmap->drawable.pScreen); ScreenPtr screen = dest->pDrawable->pScreen; - PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); PicturePtr temp_src = source, temp_mask = mask; + PixmapPtr temp_src_pixmap = source_pixmap; + PixmapPtr temp_mask_pixmap = mask_pixmap; glamor_pixmap_private *temp_src_priv = source_pixmap_priv; glamor_pixmap_private *temp_mask_priv = mask_pixmap_priv; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; @@ -1415,7 +1376,7 @@ glamor_composite_clipped_region(CARD8 op, int height; BoxPtr box; int nbox; - Bool two_pass_ca = FALSE; + enum ca_state ca_state = CA_NONE; extent = RegionExtents(region); box = RegionRects(region); @@ -1431,12 +1392,6 @@ glamor_composite_clipped_region(CARD8 op, DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); - if (source_pixmap_priv) - source_pixmap = source_pixmap_priv->base.pixmap; - - if (mask_pixmap_priv) - mask_pixmap = mask_pixmap_priv->base.pixmap; - /* XXX is it possible source mask have non-zero drawable.x/y? */ if (source && ((!source->pDrawable @@ -1454,8 +1409,8 @@ glamor_composite_clipped_region(CARD8 op, temp_src = source; goto out; } - temp_src_priv = - glamor_get_pixmap_private((PixmapPtr) (temp_src->pDrawable)); + temp_src_pixmap = (PixmapPtr) (temp_src->pDrawable); + temp_src_priv = glamor_get_pixmap_private(temp_src_pixmap); x_temp_src = -extent->x1 + x_dest + dest->pDrawable->x; y_temp_src = -extent->y1 + y_dest + dest->pDrawable->y; } @@ -1478,36 +1433,28 @@ glamor_composite_clipped_region(CARD8 op, temp_mask = mask; goto out; } - temp_mask_priv = - glamor_get_pixmap_private((PixmapPtr) (temp_mask->pDrawable)); + temp_mask_pixmap = (PixmapPtr) (temp_mask->pDrawable); + temp_mask_priv = glamor_get_pixmap_private(temp_mask_pixmap); x_temp_mask = -extent->x1 + x_dest + dest->pDrawable->x; y_temp_mask = -extent->y1 + y_dest + dest->pDrawable->y; } - /* Do two-pass PictOpOver componentAlpha, until we enable - * dual source color blending. - */ if (mask && mask->componentAlpha) { - if (op == PictOpOver) { - two_pass_ca = TRUE; - op = PictOpOutReverse; - } - } - - if (!mask && temp_src) { - if (glamor_composite_with_copy(op, temp_src, dest, - x_temp_src, y_temp_src, - x_dest, y_dest, region)) { - ok = TRUE; - goto out; + if (glamor_priv->has_dual_blend) { + ca_state = CA_DUAL_BLEND; + } else { + if (op == PictOpOver) { + ca_state = CA_TWO_PASS; + op = PictOpOutReverse; + } } } - if (source_pixmap == dest_pixmap) { + if (temp_src_pixmap == dest_pixmap) { glamor_fallback("source and dest pixmaps are the same\n"); goto out; } - if (mask_pixmap == dest_pixmap) { + if (temp_mask_pixmap == dest_pixmap) { glamor_fallback("mask and dest pixmaps are the same\n"); goto out; } @@ -1548,9 +1495,10 @@ glamor_composite_clipped_region(CARD8 op, DEBUGF("dest %d %d \n", prect[i].x_dst, prect[i].y_dst); } ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest, + temp_src_pixmap, temp_mask_pixmap, dest_pixmap, temp_src_priv, temp_mask_priv, dest_pixmap_priv, - box_cnt, prect, two_pass_ca); + box_cnt, prect, ca_state); if (!ok) break; nbox -= box_cnt; @@ -1568,43 +1516,35 @@ glamor_composite_clipped_region(CARD8 op, return ok; } -static Bool -_glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height, Bool fallback) +void +glamor_composite(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) { ScreenPtr screen = dest->pDrawable->pScreen; - glamor_pixmap_private *dest_pixmap_priv; - glamor_pixmap_private *source_pixmap_priv = NULL, *mask_pixmap_priv = NULL; PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - Bool ret = TRUE; RegionRec region; BoxPtr extent; int nbox, ok = FALSE; int force_clip = 0; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - if (source->pDrawable) { source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) + if (glamor_pixmap_drm_only(source_pixmap)) goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + if (glamor_pixmap_drm_only(mask_pixmap)) goto fail; } @@ -1613,14 +1553,15 @@ _glamor_composite(CARD8 op, source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + if (!glamor_pixmap_has_fbo(dest_pixmap)) goto fail; - } - if (op >= ARRAY_SIZE(composite_op_info)) + if (op >= ARRAY_SIZE(composite_op_info)) { + glamor_fallback("Unsupported composite op %x\n", op); goto fail; + } - if (mask && mask->componentAlpha) { + if (mask && mask->componentAlpha && !glamor_priv->has_dual_blend) { if (op == PictOpAtop || op == PictOpAtopReverse || op == PictOpXor || op >= PictOpSaturate) { @@ -1647,18 +1588,16 @@ _glamor_composite(CARD8 op, (mask_pixmap ? mask->pDrawable->y : 0), x_dest + dest->pDrawable->x, y_dest + dest->pDrawable->y, width, height)) { - ret = TRUE; - goto done; + return; } nbox = REGION_NUM_RECTS(®ion); DEBUGF("first clipped when compositing.\n"); DEBUGRegionPrint(®ion); extent = RegionExtents(®ion); - if (nbox == 0) { - ret = TRUE; - goto done; - } + if (nbox == 0) + return; + /* If destination is not a large pixmap, but the region is larger * than texture size limitation, and source or mask is memory pixmap, * then there may be need to load a large memory pixmap to a @@ -1667,28 +1606,28 @@ _glamor_composite(CARD8 op, * pixmap. */ if (!glamor_check_fbo_size(glamor_priv, extent->x2 - extent->x1, extent->y2 - extent->y1) - && (dest_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) - && ((source_pixmap_priv - && (source_pixmap_priv->type == GLAMOR_MEMORY || + && glamor_pixmap_is_large(dest_pixmap) + && ((source_pixmap + && (glamor_pixmap_is_memory(source_pixmap) || source->repeatType == RepeatPad)) - || (mask_pixmap_priv && - (mask_pixmap_priv->type == GLAMOR_MEMORY || + || (mask_pixmap && + (glamor_pixmap_is_memory(mask_pixmap) || mask->repeatType == RepeatPad)) - || (!source_pixmap_priv && + || (!source_pixmap && (source->pSourcePict->type != SourcePictTypeSolidFill)) - || (!mask_pixmap_priv && mask && + || (!mask_pixmap && mask && mask->pSourcePict->type != SourcePictTypeSolidFill))) force_clip = 1; - if (force_clip || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE - || (source_pixmap_priv - && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) - || (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)) + if (force_clip || glamor_pixmap_is_large(dest_pixmap) + || (source_pixmap + && glamor_pixmap_is_large(source_pixmap)) + || (mask_pixmap && glamor_pixmap_is_large(mask_pixmap))) ok = glamor_composite_largepixmap_region(op, source, mask, dest, - source_pixmap_priv, - mask_pixmap_priv, - dest_pixmap_priv, + source_pixmap, + mask_pixmap, + dest_pixmap, ®ion, force_clip, x_source, y_source, x_mask, y_mask, @@ -1696,9 +1635,9 @@ _glamor_composite(CARD8 op, else ok = glamor_composite_clipped_region(op, source, mask, dest, - source_pixmap_priv, - mask_pixmap_priv, - dest_pixmap_priv, + source_pixmap, + mask_pixmap, + dest_pixmap, ®ion, x_source, y_source, x_mask, y_mask, x_dest, y_dest); @@ -1706,17 +1645,9 @@ _glamor_composite(CARD8 op, REGION_UNINIT(dest->pDrawable->pScreen, ®ion); if (ok) - goto done; - fail: + return; - if (!fallback && glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable) - && (!source_pixmap - || glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable)) - && (!mask_pixmap - || glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) { - ret = FALSE; - goto done; - } + fail: glamor_fallback ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", @@ -1747,192 +1678,4 @@ _glamor_composite(CARD8 op, glamor_finish_access_picture(mask); glamor_finish_access_picture(source); glamor_finish_access_picture(dest); - - done: - return ret; } - -void -glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) -{ - _glamor_composite(op, source, mask, dest, x_source, y_source, - x_mask, y_mask, x_dest, y_dest, width, height, TRUE); -} - -Bool -glamor_composite_nf(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) -{ - return _glamor_composite(op, source, mask, dest, x_source, y_source, - x_mask, y_mask, x_dest, y_dest, width, height, - FALSE); -} - -static void -glamor_get_src_rect_extent(int nrect, - glamor_composite_rect_t *rects, BoxPtr extent) -{ - extent->x1 = MAXSHORT; - extent->y1 = MAXSHORT; - extent->x2 = MINSHORT; - extent->y2 = MINSHORT; - - while (nrect--) { - if (extent->x1 > rects->x_src) - extent->x1 = rects->x_src; - if (extent->y1 > rects->y_src) - extent->y1 = rects->y_src; - if (extent->x2 < rects->x_src + rects->width) - extent->x2 = rects->x_src + rects->width; - if (extent->y2 < rects->y_src + rects->height) - extent->y2 = rects->y_src + rects->height; - rects++; - } -} - -static void -glamor_composite_src_rect_translate(int nrect, - glamor_composite_rect_t *rects, - int x, int y) -{ - while (nrect--) { - rects->x_src += x; - rects->y_src += y; - rects++; - } -} - -void -glamor_composite_glyph_rects(CARD8 op, - PicturePtr src, PicturePtr mask, PicturePtr dst, - int nrect, glamor_composite_rect_t *rects) -{ - int n; - PicturePtr temp_src = NULL; - glamor_composite_rect_t *r; - - ValidatePicture(src); - ValidatePicture(dst); - if (!(glamor_is_large_picture(src) - || (mask && glamor_is_large_picture(mask)) - || glamor_is_large_picture(dst))) { - glamor_pixmap_private *src_pixmap_priv = NULL; - glamor_pixmap_private *mask_pixmap_priv = NULL; - glamor_pixmap_private *dst_pixmap_priv; - glamor_pixmap_private *temp_src_priv = NULL; - BoxRec src_extent; - - dst_pixmap_priv = glamor_get_pixmap_private - (glamor_get_drawable_pixmap(dst->pDrawable)); - - if (mask && mask->pDrawable) - mask_pixmap_priv = glamor_get_pixmap_private - (glamor_get_drawable_pixmap(mask->pDrawable)); - if (src->pDrawable) - src_pixmap_priv = glamor_get_pixmap_private - (glamor_get_drawable_pixmap(src->pDrawable)); - - if (!src->pDrawable - && (src->pSourcePict->type != SourcePictTypeSolidFill)) { - glamor_get_src_rect_extent(nrect, rects, &src_extent); - temp_src = glamor_convert_gradient_picture(dst->pDrawable->pScreen, - src, - src_extent.x1, - src_extent.y1, - src_extent.x2 - - src_extent.x1, - src_extent.y2 - - src_extent.y1); - if (!temp_src) - goto fallback; - - temp_src_priv = glamor_get_pixmap_private - ((PixmapPtr) (temp_src->pDrawable)); - glamor_composite_src_rect_translate(nrect, rects, - -src_extent.x1, -src_extent.y1); - } - else { - temp_src = src; - temp_src_priv = src_pixmap_priv; - } - - if (mask && mask->componentAlpha) { - if (op == PictOpOver) { - if (glamor_composite_with_shader(PictOpOutReverse, - temp_src, mask, dst, - temp_src_priv, - mask_pixmap_priv, - dst_pixmap_priv, nrect, rects, - TRUE)) - goto done; - } - } - else { - if (glamor_composite_with_shader - (op, temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, - dst_pixmap_priv, nrect, rects, FALSE)) - goto done; - } - } - fallback: - n = nrect; - r = rects; - - while (n--) { - CompositePicture(op, - temp_src ? temp_src : src, - mask, - dst, - r->x_src, r->y_src, - r->x_mask, r->y_mask, - r->x_dst, r->y_dst, r->width, r->height); - r++; - } - - done: - if (temp_src && temp_src != src) - FreePicture(temp_src, 0); -} - -static Bool -_glamor_composite_rects(CARD8 op, - PicturePtr pDst, - xRenderColor *color, - int nRect, xRectangle *rects, Bool fallback) -{ - miCompositeRects(op, pDst, color, nRect, rects); - return TRUE; -} - -void -glamor_composite_rects(CARD8 op, - PicturePtr pDst, - xRenderColor *color, int nRect, xRectangle *rects) -{ - _glamor_composite_rects(op, pDst, color, nRect, rects, TRUE); -} - -Bool -glamor_composite_rects_nf(CARD8 op, - PicturePtr pDst, - xRenderColor *color, int nRect, xRectangle *rects) -{ - return _glamor_composite_rects(op, pDst, color, nRect, rects, FALSE); -} - -#endif /* RENDER */ diff --git a/xserver/glamor/glamor_segs.c b/xserver/glamor/glamor_segs.c index ff0daef10..5fffa3b0f 100644 --- a/xserver/glamor/glamor_segs.c +++ b/xserver/glamor/glamor_segs.c @@ -44,7 +44,7 @@ glamor_poly_segment_solid_gl(DrawablePtr drawable, GCPtr gc, int off_x, off_y; xSegment *v; char *vbo_offset; - int box_x, box_y; + int box_index; int add_last; pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -91,11 +91,11 @@ glamor_poly_segment_solid_gl(DrawablePtr drawable, GCPtr gc, glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); - glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE, + glamor_set_destination_drawable(drawable, box_index, TRUE, TRUE, prog->matrix_uniform, &off_x, &off_y); while (nbox--) { @@ -109,12 +109,10 @@ glamor_poly_segment_solid_gl(DrawablePtr drawable, GCPtr gc, } glDisable(GL_SCISSOR_TEST); - glDisable(GL_COLOR_LOGIC_OP); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); return TRUE; bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } @@ -168,21 +166,3 @@ glamor_poly_segment(DrawablePtr drawable, GCPtr gc, glamor_poly_segment_bail(drawable, gc, nseg, segs); } - -Bool -glamor_poly_segment_nf(DrawablePtr drawable, GCPtr gc, - int nseg, xSegment *segs) -{ - if (glamor_poly_segment_gl(drawable, gc, nseg, segs)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable) && - glamor_ddx_fallback_check_gc(gc)) - { - return FALSE; - } - - glamor_poly_segment_bail(drawable, gc, nseg, segs); - return TRUE; -} - diff --git a/xserver/glamor/glamor_spans.c b/xserver/glamor/glamor_spans.c index 6ebb12e18..89a9c5102 100644 --- a/xserver/glamor/glamor_spans.c +++ b/xserver/glamor/glamor_spans.c @@ -55,7 +55,7 @@ glamor_fill_spans_gl(DrawablePtr drawable, GLshort *v; char *vbo_offset; int c; - int box_x, box_y; + int box_index; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -68,7 +68,7 @@ glamor_fill_spans_gl(DrawablePtr drawable, &glamor_facet_fillspans_130); if (!prog) - goto bail_ctx; + goto bail; /* Set up the vertex buffers for the points */ @@ -93,7 +93,7 @@ glamor_fill_spans_gl(DrawablePtr drawable, &glamor_facet_fillspans_120); if (!prog) - goto bail_ctx; + goto bail; /* Set up the vertex buffers for the points */ @@ -119,11 +119,12 @@ glamor_fill_spans_gl(DrawablePtr drawable, glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); - glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, FALSE, prog->matrix_uniform, &off_x, &off_y); + glamor_set_destination_drawable(drawable, box_index, FALSE, FALSE, + prog->matrix_uniform, &off_x, &off_y); while (nbox--) { glScissor(box->x1 + off_x, @@ -134,27 +135,17 @@ glamor_fill_spans_gl(DrawablePtr drawable, if (glamor_priv->glsl_version >= 130) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n); else { - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - glDrawArrays(GL_QUADS, 0, 4 * n); - } else { - int i; - for (i = 0; i < n; i++) { - glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); - } - } + glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox); } } } glDisable(GL_SCISSOR_TEST); - glDisable(GL_COLOR_LOGIC_OP); if (glamor_priv->glsl_version >= 130) glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); return TRUE; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } @@ -182,21 +173,6 @@ glamor_fill_spans(DrawablePtr drawable, glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted); } -Bool -glamor_fill_spans_nf(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted) -{ - if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) - return FALSE; - - glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted); - return TRUE; -} - static Bool glamor_get_spans_gl(DrawablePtr drawable, int wmax, DDXPointPtr points, int *widths, int count, char *dst) @@ -205,7 +181,7 @@ glamor_get_spans_gl(DrawablePtr drawable, int wmax, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv; - int box_x, box_y; + int box_index; int n; char *d; GLenum type; @@ -222,9 +198,9 @@ glamor_get_spans_gl(DrawablePtr drawable, int wmax, glamor_make_current(glamor_priv); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { - BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); - glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y); + glamor_pixmap_loop(pixmap_priv, box_index) { + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_index); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_index); glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); glPixelStorei(GL_PACK_ALIGNMENT, 4); @@ -282,20 +258,6 @@ glamor_get_spans(DrawablePtr drawable, int wmax, glamor_get_spans_bail(drawable, wmax, points, widths, count, dst); } -Bool -glamor_get_spans_nf(DrawablePtr drawable, int wmax, - DDXPointPtr points, int *widths, int count, char *dst) -{ - if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable)) - return FALSE; - - glamor_get_spans_bail(drawable, wmax, points, widths, count, dst); - return TRUE; -} - static Bool glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int numPoints, int sorted) @@ -304,7 +266,7 @@ 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; - int box_x, box_y; + int box_index; int n; char *s; GLenum type; @@ -318,7 +280,7 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, if (gc->alu != GXcopy) goto bail; - if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask)) + if (!glamor_pm_is_solid(gc->depth, gc->planemask)) goto bail; glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); @@ -328,9 +290,9 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { - BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); - glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y); + glamor_pixmap_loop(pixmap_priv, box_index) { + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_index); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_index); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, fbo->tex); @@ -415,17 +377,3 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, return; glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted); } - -Bool -glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int numPoints, int sorted) -{ - if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) - return FALSE; - - glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted); - return TRUE; -} diff --git a/xserver/glamor/glamor_text.c b/xserver/glamor/glamor_text.c index 59cd0fdc8..c305305f4 100644 --- a/xserver/glamor/glamor_text.c +++ b/xserver/glamor/glamor_text.c @@ -107,7 +107,7 @@ glamor_text(DrawablePtr drawable, GCPtr gc, int firstCol = font->info.firstCol; int glyph_spacing_x = glamor_font->glyph_width_bytes * 8; int glyph_spacing_y = glamor_font->glyph_height; - int box_x, box_y; + int box_index; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -142,7 +142,7 @@ glamor_text(DrawablePtr drawable, GCPtr gc, int height = GLYPHHEIGHTPIXELS(ci); int tx, ty = 0; int row = 0, col; - + int second_row = 0; x += ci->metrics.characterWidth; if (sixteen) { @@ -153,8 +153,10 @@ glamor_text(DrawablePtr drawable, GCPtr gc, row = chars[0]; col = chars[1]; } - if (FONTLASTROW(font) != 0) - ty = (row - firstRow) * glyph_spacing_y; + if (FONTLASTROW(font) != 0) { + ty = ((row - firstRow) / 2) * glyph_spacing_y; + second_row = (row - firstRow) & 1; + } else col += row << 8; } else { @@ -165,6 +167,8 @@ glamor_text(DrawablePtr drawable, GCPtr gc, } tx = (col - firstCol) * glyph_spacing_x; + /* adjust for second row layout */ + tx += second_row * glamor_font->row_width * 8; v[ 0] = x1; v[ 1] = y1; @@ -184,11 +188,13 @@ glamor_text(DrawablePtr drawable, GCPtr gc, glEnable(GL_SCISSOR_TEST); - glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + glamor_pixmap_loop(pixmap_priv, box_index) { BoxPtr box = RegionRects(gc->pCompositeClip); int nbox = RegionNumRects(gc->pCompositeClip); - glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); + glamor_set_destination_drawable(drawable, box_index, TRUE, FALSE, + prog->matrix_uniform, + &off_x, &off_y); /* Run over the clip list, drawing the glyphs * in each box @@ -210,7 +216,6 @@ glamor_text(DrawablePtr drawable, GCPtr gc, glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisable(GL_COLOR_LOGIC_OP); return x; } @@ -286,34 +291,18 @@ glamor_poly_text(DrawablePtr drawable, GCPtr gc, prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_text_progs, &glamor_facet_poly_text); if (!prog) - goto bail_ctx; + goto bail; x = glamor_text(drawable, gc, glamor_font, prog, x, y, count, chars, charinfo, sixteen); - glDisable(GL_COLOR_LOGIC_OP); - *final_pos = x; return TRUE; -bail_ctx: - glDisable(GL_COLOR_LOGIC_OP); bail: return FALSE; } -Bool -glamor_poly_text8_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, char *chars, int *final_pos) -{ - if (glamor_poly_text(drawable, gc, x, y, count, chars, FALSE, final_pos)) - return TRUE; - if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) - return FALSE; - *final_pos = miPolyText8(drawable, gc, x, y, count, chars); - return TRUE; -} - int glamor_poly_text8(DrawablePtr drawable, GCPtr gc, int x, int y, int count, char *chars) @@ -325,19 +314,6 @@ glamor_poly_text8(DrawablePtr drawable, GCPtr gc, return miPolyText8(drawable, gc, x, y, count, chars); } -Bool -glamor_poly_text16_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, unsigned short *chars, int *final_pos) -{ - if (glamor_poly_text(drawable, gc, x, y, count, (char *) chars, TRUE, final_pos)) - return TRUE; - - if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) - return FALSE; - *final_pos = miPolyText16(drawable, gc, x, y, count, chars); - return TRUE; -} - int glamor_poly_text16(DrawablePtr drawable, GCPtr gc, int x, int y, int count, unsigned short *chars) @@ -447,7 +423,7 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc, fill_facet = &glamor_facet_image_fill; } - if (!glamor_build_program(screen, prog, prim_facet, fill_facet)) + if (!glamor_build_program(screen, prog, prim_facet, fill_facet, NULL, NULL)) goto bail; } @@ -461,7 +437,7 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc, /* Check planemask before drawing background to * bail early if it's not OK */ - if (!glamor_set_planemask(pixmap, gc->planemask)) + if (!glamor_set_planemask(gc->depth, gc->planemask)) goto bail; for (c = 0; c < count; c++) if (charinfo[c]) @@ -493,17 +469,9 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc, return TRUE; bail: - glDisable(GL_COLOR_LOGIC_OP); return FALSE; } -Bool -glamor_image_text8_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, char *chars) -{ - return glamor_image_text(drawable, gc, x, y, count, chars, FALSE); -} - void glamor_image_text8(DrawablePtr drawable, GCPtr gc, int x, int y, int count, char *chars) @@ -512,13 +480,6 @@ glamor_image_text8(DrawablePtr drawable, GCPtr gc, miImageText8(drawable, gc, x, y, count, chars); } -Bool -glamor_image_text16_nf(DrawablePtr drawable, GCPtr gc, - int x, int y, int count, unsigned short *chars) -{ - return glamor_image_text(drawable, gc, x, y, count, (char *) chars, TRUE); -} - void glamor_image_text16(DrawablePtr drawable, GCPtr gc, int x, int y, int count, unsigned short *chars) diff --git a/xserver/glamor/glamor_transfer.c b/xserver/glamor/glamor_transfer.c index aa5e8616e..ed81195b6 100644 --- a/xserver/glamor/glamor_transfer.c +++ b/xserver/glamor/glamor_transfer.c @@ -42,7 +42,7 @@ glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type) *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; break; case 8: - *format = GL_ALPHA; + *format = glamor_get_screen_private(pixmap->drawable.pScreen)->one_channel_format; *type = GL_UNSIGNED_BYTE; break; default: @@ -63,7 +63,7 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); - int box_x, box_y; + int box_index; int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3; GLenum type; GLenum format; @@ -77,9 +77,9 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, if (glamor_priv->has_unpack_subimage) glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel); - glamor_pixmap_loop(priv, box_x, box_y) { - BoxPtr box = glamor_pixmap_box_at(priv, box_x, box_y); - glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y); + glamor_pixmap_loop(priv, box_index) { + BoxPtr box = glamor_pixmap_box_at(priv, box_index); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_index); BoxPtr boxes = in_boxes; int nbox = in_nbox; @@ -167,7 +167,7 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); - int box_x, box_y; + int box_index; int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3; GLenum type; GLenum format; @@ -180,12 +180,14 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, if (glamor_priv->has_pack_subimage) glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel); - glamor_pixmap_loop(priv, box_x, box_y) { - BoxPtr box = glamor_pixmap_box_at(priv, box_x, box_y); - glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y); + glamor_pixmap_loop(priv, box_index) { + BoxPtr box = glamor_pixmap_box_at(priv, box_index); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_index); BoxPtr boxes = in_boxes; int nbox = in_nbox; + /* This should not be called on GLAMOR_FBO_NO_FBO-allocated pixmaps. */ + assert(fbo->fb); glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); while (nbox--) { diff --git a/xserver/glamor/glamor_transform.c b/xserver/glamor/glamor_transform.c index c1df56018..fc96fd670 100644 --- a/xserver/glamor/glamor_transform.c +++ b/xserver/glamor/glamor_transform.c @@ -35,18 +35,19 @@ void glamor_set_destination_drawable(DrawablePtr drawable, - int box_x, - int box_y, + int box_index, Bool do_drawable_translate, Bool center_offset, GLint matrix_uniform_location, int *p_off_x, int *p_off_y) { + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int off_x, off_y; - BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_index); int w = box->x2 - box->x1; int h = box->y2 - box->y1; float scale_x = 2.0f / (float) w; @@ -75,8 +76,6 @@ glamor_set_destination_drawable(DrawablePtr drawable, * gl_x = (render_x + drawable->x + off_x) * 2 / width - 1 * * gl_x = (render_x) * 2 / width + (drawable->x + off_x) * 2 / width - 1 - * - * I'll think about yInverted later, when I have some way to test */ if (do_drawable_translate) { @@ -95,7 +94,7 @@ glamor_set_destination_drawable(DrawablePtr drawable, scale_x, (off_x + center_adjust) * scale_x - 1.0f, scale_y, (off_y + center_adjust) * scale_y - 1.0f); - glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y), + glamor_set_destination_pixmap_fbo(glamor_priv, glamor_pixmap_fbo_at(pixmap_priv, box_index), 0, 0, w, h); } @@ -105,15 +104,21 @@ glamor_set_destination_drawable(DrawablePtr drawable, */ void -glamor_set_color(PixmapPtr pixmap, - CARD32 pixel, - GLint uniform) +glamor_set_color_depth(ScreenPtr pScreen, + int depth, + CARD32 pixel, + GLint uniform) { + glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); float color[4]; glamor_get_rgba_from_pixel(pixel, &color[0], &color[1], &color[2], &color[3], - format_for_pixmap(pixmap)); + format_for_depth(depth)); + + if ((depth == 1 || depth == 8) && + glamor_priv->one_channel_format == GL_RED) + color[0] = color[3]; glUniform4fv(uniform, 1, color); } @@ -127,7 +132,7 @@ glamor_set_solid(PixmapPtr pixmap, CARD32 pixel; int alu = use_alu ? gc->alu : GXcopy; - if (!glamor_set_planemask(pixmap, gc->planemask)) + if (!glamor_set_planemask(gc->depth, gc->planemask)) return FALSE; pixel = gc->fgPixel; @@ -153,12 +158,7 @@ glamor_set_solid(PixmapPtr pixmap, } Bool -glamor_set_texture(PixmapPtr pixmap, - PixmapPtr texture, - int off_x, - int off_y, - GLint offset_uniform, - GLint size_uniform) +glamor_set_texture_pixmap(PixmapPtr texture) { glamor_pixmap_private *texture_priv; @@ -167,14 +167,31 @@ glamor_set_texture(PixmapPtr pixmap, if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv)) return FALSE; - if (texture_priv->type == GLAMOR_TEXTURE_LARGE) + if (glamor_pixmap_priv_is_large(texture_priv)) return FALSE; glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture_priv->base.fbo->tex); + glBindTexture(GL_TEXTURE_2D, texture_priv->fbo->tex); + + /* we're not setting the sampler uniform here as we always use + * GL_TEXTURE0, and the default value for uniforms is zero. So, + * save a bit of CPU time by taking advantage of that. + */ + return TRUE; +} + +Bool +glamor_set_texture(PixmapPtr texture, + int off_x, + int off_y, + GLint offset_uniform, + GLint size_inv_uniform) +{ + if (!glamor_set_texture_pixmap(texture)) + return FALSE; glUniform2f(offset_uniform, off_x, off_y); - glUniform2f(size_uniform, texture->drawable.width, texture->drawable.height); + glUniform2f(size_inv_uniform, 1.0f/texture->drawable.width, 1.0f/texture->drawable.height); return TRUE; } @@ -182,20 +199,19 @@ Bool glamor_set_tiled(PixmapPtr pixmap, GCPtr gc, GLint offset_uniform, - GLint size_uniform) + GLint size_inv_uniform) { if (!glamor_set_alu(pixmap->drawable.pScreen, gc->alu)) return FALSE; - if (!glamor_set_planemask(pixmap, gc->planemask)) + if (!glamor_set_planemask(gc->depth, gc->planemask)) return FALSE; - return glamor_set_texture(pixmap, - gc->tile.pixmap, + return glamor_set_texture(gc->tile.pixmap, -gc->patOrg.x, -gc->patOrg.y, offset_uniform, - size_uniform); + size_inv_uniform); } static PixmapPtr @@ -272,8 +288,7 @@ glamor_set_stippled(PixmapPtr pixmap, if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform)) return FALSE; - return glamor_set_texture(pixmap, - stipple, + return glamor_set_texture(stipple, -gc->patOrg.x, -gc->patOrg.y, offset_uniform, diff --git a/xserver/glamor/glamor_transform.h b/xserver/glamor/glamor_transform.h index 36b789af8..5a520ebb0 100644 --- a/xserver/glamor/glamor_transform.h +++ b/xserver/glamor/glamor_transform.h @@ -25,8 +25,7 @@ void glamor_set_destination_drawable(DrawablePtr drawable, - int box_x, - int box_y, + int box_index, Bool do_drawable_translate, Bool center_offset, GLint matrix_uniform_location, @@ -34,13 +33,25 @@ glamor_set_destination_drawable(DrawablePtr drawable, int *p_off_y); void +glamor_set_color_depth(ScreenPtr pScreen, + int depth, + CARD32 pixel, + GLint uniform); + +static inline void glamor_set_color(PixmapPtr pixmap, CARD32 pixel, - GLint uniform); + GLint uniform) +{ + glamor_set_color_depth(pixmap->drawable.pScreen, + pixmap->drawable.depth, pixel, uniform); +} + +Bool +glamor_set_texture_pixmap(PixmapPtr texture); Bool -glamor_set_texture(PixmapPtr pixmap, - PixmapPtr texture, +glamor_set_texture(PixmapPtr texture, int off_x, int off_y, GLint offset_uniform, diff --git a/xserver/glamor/glamor_trapezoid.c b/xserver/glamor/glamor_trapezoid.c index f8bf6c97f..a448a6b3e 100644 --- a/xserver/glamor/glamor_trapezoid.c +++ b/xserver/glamor/glamor_trapezoid.c @@ -32,7 +32,6 @@ #include "glamor_priv.h" -#ifdef RENDER #include "mipict.h" #include "fbpict.h" @@ -155,18 +154,3 @@ glamor_trapezoids(CARD8 op, FreePicture(picture, 0); } - -Bool -glamor_trapezoids_nf(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid *traps) -{ - DEBUGF("x_src = %d, y_src = %d, ntrap = %d\n", x_src, y_src, ntrap); - - glamor_trapezoids(op, src, dst, mask_format, x_src, - y_src, ntrap, traps); - return TRUE; -} - -#endif /* RENDER */ diff --git a/xserver/glamor/glamor_triangles.c b/xserver/glamor/glamor_triangles.c index b89cb2de7..88a46c11f 100644 --- a/xserver/glamor/glamor_triangles.c +++ b/xserver/glamor/glamor_triangles.c @@ -28,29 +28,6 @@ #include "glamor_priv.h" -static Bool -_glamor_triangles(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris, - Bool fallback) -{ - if (!fallback && glamor_ddx_fallback_check_pixmap(pDst->pDrawable) - && (!pSrc->pDrawable - || glamor_ddx_fallback_check_pixmap(pSrc->pDrawable))) - return FALSE; - - if (glamor_prepare_access_picture(pDst, GLAMOR_ACCESS_RW) && - glamor_prepare_access_picture(pSrc, GLAMOR_ACCESS_RO)) { - fbTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntris, tris); - } - glamor_finish_access_picture(pSrc); - glamor_finish_access_picture(pDst); - - return TRUE; -} - void glamor_triangles(CARD8 op, PicturePtr pSrc, @@ -58,17 +35,10 @@ glamor_triangles(CARD8 op, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris) { - _glamor_triangles(op, pSrc, pDst, maskFormat, - xSrc, ySrc, ntris, tris, TRUE); -} - -Bool -glamor_triangles_nf(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris) -{ - return _glamor_triangles(op, pSrc, pDst, maskFormat, - xSrc, ySrc, ntris, tris, FALSE); + if (glamor_prepare_access_picture(pDst, GLAMOR_ACCESS_RW) && + glamor_prepare_access_picture(pSrc, GLAMOR_ACCESS_RO)) { + fbTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntris, tris); + } + glamor_finish_access_picture(pSrc); + glamor_finish_access_picture(pDst); } diff --git a/xserver/glamor/glamor_utils.c b/xserver/glamor/glamor_utils.c index f06896096..d3e6fd3ff 100644 --- a/xserver/glamor/glamor_utils.c +++ b/xserver/glamor/glamor_utils.c @@ -31,7 +31,7 @@ glamor_solid_boxes(PixmapPtr pixmap, xRectangle *rect; int n; - rect = malloc(nbox * sizeof (xRectangle)); + rect = xallocarray(nbox, sizeof(xRectangle)); if (!rect) return; for (n = 0; n < nbox; n++) { diff --git a/xserver/glamor/glamor_utils.h b/xserver/glamor/glamor_utils.h index c15d17ca3..5128a33d8 100644 --- a/xserver/glamor/glamor_utils.h +++ b/xserver/glamor/glamor_utils.h @@ -33,58 +33,53 @@ #define __GLAMOR_UTILS_H__ #include "glamor_prepare.h" +#include "mipict.h" #define v_from_x_coord_x(_xscale_, _x_) ( 2 * (_x_) * (_xscale_) - 1.0) -#define v_from_x_coord_y(_yscale_, _y_) (-2 * (_y_) * (_yscale_) + 1.0) -#define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0) +#define v_from_x_coord_y(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0) #define t_from_x_coord_x(_xscale_, _x_) ((_x_) * (_xscale_)) -#define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_)) -#define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) +#define t_from_x_coord_y(_yscale_, _y_) ((_y_) * (_yscale_)) -#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ +#define pixmap_priv_get_dest_scale(pixmap, _pixmap_priv_, _pxscale_, _pyscale_) \ do { \ int _w_,_h_; \ - PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, _w_, _h_); \ + PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap, _pixmap_priv_, _w_, _h_); \ *(_pxscale_) = 1.0 / _w_; \ *(_pyscale_) = 1.0 / _h_; \ } while(0) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ do { \ - *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.fbo->width; \ - *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.fbo->height; \ + *(_pxscale_) = 1.0 / (_pixmap_priv_)->fbo->width; \ + *(_pyscale_) = 1.0 / (_pixmap_priv_)->fbo->height; \ } while(0) -#define GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(priv) \ - (priv->base.fbo->width != priv->base.pixmap->drawable.width \ - || priv->base.fbo->height != priv->base.pixmap->drawable.height) \ - -#define PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, w, h) \ +#define PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap, priv, w, h) \ do { \ - if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \ - w = priv->large.box.x2 - priv->large.box.x1; \ - h = priv->large.box.y2 - priv->large.box.y1; \ + if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) { \ + w = priv->box.x2 - priv->box.x1; \ + h = priv->box.y2 - priv->box.y1; \ } else { \ - w = priv->base.pixmap->drawable.width; \ - h = priv->base.pixmap->drawable.height; \ + w = (pixmap)->drawable.width; \ + h = (pixmap)->drawable.height; \ } \ } while(0) -#define glamor_pixmap_fbo_fix_wh_ratio(wh, priv) \ +#define glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap, priv) \ do { \ int actual_w, actual_h; \ - PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, actual_w, actual_h); \ - wh[0] = (float)priv->base.fbo->width / actual_w; \ - wh[1] = (float)priv->base.fbo->height / actual_h; \ - wh[2] = 1.0 / priv->base.fbo->width; \ - wh[3] = 1.0 / priv->base.fbo->height; \ + PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap, priv, actual_w, actual_h); \ + wh[0] = (float)priv->fbo->width / actual_w; \ + wh[1] = (float)priv->fbo->height / actual_h; \ + wh[2] = 1.0 / priv->fbo->width; \ + wh[3] = 1.0 / priv->fbo->height; \ } while(0) #define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_) \ do { \ - if (_X_UNLIKELY(_priv_ && (_priv_)->type == GLAMOR_TEXTURE_LARGE)) { \ - *(_xoff_) = - (_priv_)->large.box.x1; \ - *(_yoff_) = - (_priv_)->large.box.y1; \ + if (_X_UNLIKELY(_priv_ && glamor_pixmap_priv_is_large(_priv_))) { \ + *(_xoff_) = - (_priv_)->box.x1; \ + *(_yoff_) = - (_priv_)->box.y1; \ } else { \ *(_xoff_) = 0; \ *(_yoff_) = 0; \ @@ -193,33 +188,33 @@ txy = xy - bxy1; \ } while(0) -#define _glamor_get_reflect_transform_coords(priv, repeat_type, \ +#define _glamor_get_reflect_transform_coords(pixmap, priv, repeat_type, \ tx1, ty1, \ _x1_, _y1_) \ do { \ int odd_x, odd_y; \ float c, d; \ fodd_repeat_mod(_x1_,priv->box.x2, \ - priv->base.pixmap->drawable.width, \ + (pixmap)->drawable.width, \ odd_x, c); \ fodd_repeat_mod(_y1_, priv->box.y2, \ - priv->base.pixmap->drawable.height, \ + (pixmap)->drawable.height, \ odd_y, d); \ DEBUGF("c %f d %f oddx %d oddy %d \n", \ c, d, odd_x, odd_y); \ DEBUGF("x2 %d x1 %d fbo->width %d \n", priv->box.x2, \ - priv->box.x1, priv->base.fbo->width); \ + priv->box.x1, priv->fbo->width); \ DEBUGF("y2 %d y1 %d fbo->height %d \n", priv->box.y2, \ - priv->box.y1, priv->base.fbo->height); \ + priv->box.y1, priv->fbo->height); \ _glamor_repeat_reflect_fixup(tx1, _x1_, c, odd_x, \ - priv->base.pixmap->drawable.width, \ + (pixmap)->drawable.width, \ priv->box.x1, priv->box.x2); \ _glamor_repeat_reflect_fixup(ty1, _y1_, d, odd_y, \ - priv->base.pixmap->drawable.height, \ + (pixmap)->drawable.height, \ priv->box.y1, priv->box.y2); \ } while(0) -#define _glamor_get_repeat_coords(priv, repeat_type, tx1, \ +#define _glamor_get_repeat_coords(pixmap, priv, repeat_type, tx1, \ ty1, tx2, ty2, \ _x1_, _y1_, _x2_, \ _y2_, c, d, odd_x, odd_y) \ @@ -228,10 +223,10 @@ DEBUGF("x1 y1 %d %d\n", \ _x1_, _y1_ ); \ DEBUGF("width %d box.x1 %d \n", \ - (priv)->base.pixmap->drawable.width, \ + (pixmap)->drawable.width, \ priv->box.x1); \ if (odd_x) { \ - c = (priv)->base.pixmap->drawable.width \ + c = (pixmap)->drawable.width \ - c; \ tx1 = c - priv->box.x1; \ tx2 = tx1 - ((_x2_) - (_x1_)); \ @@ -240,7 +235,7 @@ tx2 = tx1 + ((_x2_) - (_x1_)); \ } \ if (odd_y){ \ - d = (priv)->base.pixmap->drawable.height\ + d = (pixmap)->drawable.height\ - d; \ ty1 = d - priv->box.y1; \ ty2 = ty1 - ((_y2_) - (_y1_)); \ @@ -257,11 +252,11 @@ } while(0) /* _x1_ ... _y2_ may has fractional. */ -#define glamor_get_repeat_transform_coords(priv, repeat_type, tx1, \ +#define glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, tx1, \ ty1, _x1_, _y1_) \ do { \ DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \ - (priv)->base.pixmap->drawable.width, \ + (pixmap)->drawable.width, \ priv->box.x1, priv->box.x2, priv->box.y1, \ priv->box.y2); \ DEBUGF("x1 %f y1 %f \n", _x1_, _y1_); \ @@ -269,33 +264,33 @@ tx1 = _x1_ - priv->box.x1; \ ty1 = _y1_ - priv->box.y1; \ } else \ - _glamor_get_reflect_transform_coords(priv, repeat_type, \ + _glamor_get_reflect_transform_coords(pixmap, priv, repeat_type, \ tx1, ty1, \ _x1_, _y1_); \ DEBUGF("tx1 %f ty1 %f \n", tx1, ty1); \ } while(0) /* _x1_ ... _y2_ must be integer. */ -#define glamor_get_repeat_coords(priv, repeat_type, tx1, \ +#define glamor_get_repeat_coords(pixmap, priv, repeat_type, tx1, \ ty1, tx2, ty2, _x1_, _y1_, _x2_, \ _y2_) \ do { \ int c, d; \ int odd_x = 0, odd_y = 0; \ DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \ - (priv)->base.pixmap->drawable.width, \ + (pixmap)->drawable.width, \ priv->box.x1, priv->box.x2, \ priv->box.y1, priv->box.y2); \ - modulus((_x1_), (priv)->base.pixmap->drawable.width, c); \ - modulus((_y1_), (priv)->base.pixmap->drawable.height, d); \ + modulus((_x1_), (pixmap)->drawable.width, c); \ + modulus((_y1_), (pixmap)->drawable.height, d); \ DEBUGF("c %d d %d \n", c, d); \ if (repeat_type == RepeatReflect) { \ odd_x = abs((_x1_ - c) \ - / (priv->base.pixmap->drawable.width)) & 1; \ + / ((pixmap)->drawable.width)) & 1; \ odd_y = abs((_y1_ - d) \ - / (priv->base.pixmap->drawable.height)) & 1; \ + / ((pixmap)->drawable.height)) & 1; \ } \ - _glamor_get_repeat_coords(priv, repeat_type, tx1, ty1, tx2, ty2,\ + _glamor_get_repeat_coords(pixmap, priv, repeat_type, tx1, ty1, tx2, ty2, \ _x1_, _y1_, _x2_, _y2_, c, d, \ odd_x, odd_y); \ } while(0) @@ -316,12 +311,12 @@ texcoord) \ do { \ (texcoord)[0] = t_from_x_coord_x(xscale, _tx_); \ - (texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_); \ + (texcoord)[1] = t_from_x_coord_y(yscale, _ty_); \ DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0], \ (texcoord)[1]); \ } while(0) -#define glamor_set_transformed_point(priv, matrix, xscale, \ +#define glamor_set_transformed_point(priv, matrix, xscale, \ yscale, texcoord, \ x, y) \ do { \ @@ -335,7 +330,7 @@ tx += fbo_x_off; \ ty += fbo_y_off; \ (texcoord)[0] = t_from_x_coord_x(xscale, tx); \ - (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \ + (texcoord)[1] = t_from_x_coord_y(yscale, ty); \ DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]); \ } while(0) @@ -404,7 +399,7 @@ texcoords+4); \ } while (0) -#define glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \ +#define glamor_set_repeat_transformed_normalize_tcoords_ext(pixmap, priv, \ repeat_type, \ matrix, \ xscale, \ @@ -414,7 +409,7 @@ texcoords, \ stride) \ do { \ - if (_X_LIKELY(priv->type != GLAMOR_TEXTURE_LARGE)) { \ + if (_X_LIKELY(glamor_pixmap_priv_is_small(priv))) { \ glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, \ yscale, _x1_, _y1_, \ _x2_, _y2_, \ @@ -429,16 +424,16 @@ glamor_transform_point(matrix, tx4, ty4, _x1_, _y2_); \ DEBUGF("transformed %f %f %f %f %f %f %f %f\n", \ tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4); \ - glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \ ttx1, tty1, \ tx1, ty1); \ - glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \ ttx2, tty2, \ tx2, ty2); \ - glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \ ttx3, tty3, \ tx3, ty3); \ - glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + glamor_get_repeat_transform_coords(pixmap, priv, repeat_type, \ ttx4, tty4, \ tx4, ty4); \ DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, \ @@ -454,7 +449,8 @@ } \ } while (0) -#define glamor_set_repeat_transformed_normalize_tcoords( priv, \ +#define glamor_set_repeat_transformed_normalize_tcoords( pixmap, \ + priv, \ repeat_type, \ matrix, \ xscale, \ @@ -463,7 +459,8 @@ _x2_, _y2_, \ texcoords) \ do { \ - glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \ + glamor_set_repeat_transformed_normalize_tcoords_ext( pixmap, \ + priv, \ repeat_type, \ matrix, \ xscale, \ @@ -485,8 +482,8 @@ (vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2); \ (vertices)[2 * stride] = _t2_; \ (vertices)[3 * stride] = _t0_; \ - (vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1); \ - (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2); \ + (vertices)[1] = _t1_ = t_from_x_coord_y(yscale, ty1); \ + (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y(yscale, ty2); \ (vertices)[1 * stride + 1] = _t1_; \ (vertices)[3 * stride + 1] = _t5_; \ } while(0) @@ -495,7 +492,7 @@ x1, y1, x2, y2, \ vertices, stride) \ do { \ - if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \ + if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) { \ float tx1, tx2, ty1, ty2; \ int fbo_x_off, fbo_y_off; \ pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ @@ -520,20 +517,20 @@ vertices, 2); \ } while(0) -#define glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \ +#define glamor_set_repeat_normalize_tcoords_ext(pixmap, priv, repeat_type, \ xscale, yscale, \ _x1_, _y1_, _x2_, _y2_, \ vertices, stride) \ do { \ - if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) { \ + if (_X_UNLIKELY(glamor_pixmap_priv_is_large(priv))) { \ float tx1, tx2, ty1, ty2; \ if (repeat_type == RepeatPad) { \ - tx1 = _x1_ - priv->large.box.x1; \ - ty1 = _y1_ - priv->large.box.y1; \ + tx1 = _x1_ - priv->box.x1; \ + ty1 = _y1_ - priv->box.y1; \ tx2 = tx1 + ((_x2_) - (_x1_)); \ ty2 = ty1 + ((_y2_) - (_y1_)); \ } else { \ - glamor_get_repeat_coords((&priv->large), repeat_type, \ + glamor_get_repeat_coords(pixmap, priv, repeat_type, \ tx1, ty1, tx2, ty2, \ _x1_, _y1_, _x2_, _y2_); \ } \ @@ -565,8 +562,8 @@ (vertices)[2] = t_from_x_coord_x(xscale, x2); \ (vertices)[6] = (vertices)[2]; \ (vertices)[4] = (vertices)[0]; \ - (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \ - (vertices)[7] = t_from_x_coord_y_inverted(yscale, y2); \ + (vertices)[1] = t_from_x_coord_y(yscale, y1); \ + (vertices)[7] = t_from_x_coord_y(yscale, y2); \ (vertices)[3] = (vertices)[1]; \ (vertices)[5] = (vertices)[7]; \ } while(0) @@ -599,7 +596,7 @@ vertices) \ do { \ (vertices)[0] = v_from_x_coord_x(xscale, x); \ - (vertices)[1] = v_from_x_coord_y_inverted(yscale, y); \ + (vertices)[1] = v_from_x_coord_y(yscale, y); \ } while(0) #define glamor_set_normalize_tri_vcoords(xscale, yscale, vtx, \ @@ -642,11 +639,9 @@ x2 + fbo_x_off); \ (vertices)[2 * stride] = _t2_; \ (vertices)[3 * stride] = _t0_; \ - (vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale, \ - y1 + fbo_y_off); \ + (vertices)[1] = _t1_ = v_from_x_coord_y(yscale, y1 + fbo_y_off); \ (vertices)[2 * stride + 1] = _t5_ = \ - v_from_x_coord_y_inverted(yscale, \ - y2 + fbo_y_off); \ + v_from_x_coord_y(yscale, y2 + fbo_y_off); \ (vertices)[1 * stride + 1] = _t1_; \ (vertices)[3 * stride + 1] = _t5_; \ } while(0) @@ -678,8 +673,8 @@ (vertices)[2] = v_from_x_coord_x(xscale, x2); \ (vertices)[6] = (vertices)[2]; \ (vertices)[4] = (vertices)[0]; \ - (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \ - (vertices)[7] = v_from_x_coord_y_inverted(yscale, y2); \ + (vertices)[1] = v_from_x_coord_y(yscale, y1); \ + (vertices)[7] = v_from_x_coord_y(yscale, y2); \ (vertices)[3] = (vertices)[1]; \ (vertices)[5] = (vertices)[7]; \ } while(0) @@ -688,7 +683,7 @@ pt) \ do { \ (pt)[0] = t_from_x_coord_x(xscale, x); \ - (pt)[1] = t_from_x_coord_y_inverted(yscale, y); \ + (pt)[1] = t_from_x_coord_y(yscale, y); \ } while(0) #define glamor_set_circle_centre(width, height, x, y, \ @@ -698,45 +693,6 @@ (c)[1] = (float)y; \ } while(0) -inline static void -glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) -{ - int x_min, y_min; - int x_max, y_max; - int i; - - x_min = y_min = MAXSHORT; - x_max = y_max = MINSHORT; - for (i = 0; i < nbox; i++) { - if (x_min > boxes[i].x1) - x_min = boxes[i].x1; - if (y_min > boxes[i].y1) - y_min = boxes[i].y1; - - if (x_max < boxes[i].x2) - x_max = boxes[i].x2; - if (y_max < boxes[i].y2) - y_max = boxes[i].y2; - } - bound->x1 = x_min; - bound->y1 = y_min; - bound->x2 = x_max; - bound->y2 = y_max; -} - -inline static void -glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy) -{ - int i; - - for (i = 0; i < nbox; i++) { - boxes[i].x1 += dx; - boxes[i].y1 += dy; - boxes[i].x2 += dx; - boxes[i].y2 += dy; - } -} - #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif @@ -758,9 +714,7 @@ glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy) || _depth_ == 30 \ || _depth_ == 32) -#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->base.is_picture == 1) -#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->base.gl_fbo == GLAMOR_FBO_NORMAL) -#define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv) (pixmap_priv && (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED)) +#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL) /** * Borrow from uxa. @@ -795,11 +749,11 @@ static inline GLenum gl_iformat_for_pixmap(PixmapPtr pixmap) { glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_get_screen_private((pixmap)->drawable.pScreen); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && - (pixmap->drawable.depth == 1 || pixmap->drawable.depth == 8)) { - return GL_ALPHA; + ((pixmap)->drawable.depth == 1 || (pixmap)->drawable.depth == 8)) { + return glamor_priv->one_channel_format; } else { return GL_RGBA; } @@ -808,16 +762,7 @@ gl_iformat_for_pixmap(PixmapPtr pixmap) static inline CARD32 format_for_pixmap(PixmapPtr pixmap) { - glamor_pixmap_private *pixmap_priv; - PictFormatShort pict_format; - - pixmap_priv = glamor_get_pixmap_private(pixmap); - if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) - pict_format = pixmap_priv->base.picture->format; - else - pict_format = format_for_depth(pixmap->drawable.depth); - - return pict_format; + return format_for_depth((pixmap)->drawable.depth); } #define REVERT_NONE 0 @@ -836,21 +781,6 @@ format_for_pixmap(PixmapPtr pixmap) #define SWAP_UPLOADING 2 #define SWAP_NONE_UPLOADING 3 -inline static int -cache_format(GLenum format) -{ - switch (format) { - case GL_ALPHA: - return 2; - case GL_RGB: - return 1; - case GL_RGBA: - return 0; - default: - return -1; - } -} - /* borrowed from uxa */ static inline Bool glamor_get_rgba_from_pixel(CARD32 pixel, @@ -922,91 +852,20 @@ glamor_get_rgba_from_pixel(CARD32 pixel, } inline static Bool -glamor_pict_format_is_compatible(PicturePtr picture) -{ - GLenum iformat; - PixmapPtr pixmap = glamor_get_drawable_pixmap(picture->pDrawable); - - iformat = gl_iformat_for_pixmap(pixmap); - switch (iformat) { - case GL_RGBA: - return (picture->format == PICT_a8r8g8b8 || - picture->format == PICT_x8r8g8b8); - case GL_ALPHA: - return (picture->format == PICT_a8); - default: - return FALSE; - } -} - -/* return TRUE if we can access this pixmap at DDX driver. */ -inline static Bool -glamor_ddx_fallback_check_pixmap(DrawablePtr drawable) -{ - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - - return (!pixmap_priv - || (pixmap_priv->type == GLAMOR_TEXTURE_DRM - || pixmap_priv->type == GLAMOR_MEMORY - || pixmap_priv->type == GLAMOR_DRM_ONLY)); -} - -inline static Bool -glamor_ddx_fallback_check_gc(GCPtr gc) -{ - PixmapPtr pixmap; - - if (!gc) - return TRUE; - switch (gc->fillStyle) { - case FillStippled: - case FillOpaqueStippled: - pixmap = gc->stipple; - break; - case FillTiled: - pixmap = gc->tile.pixmap; - break; - default: - pixmap = NULL; - } - return (!pixmap || glamor_ddx_fallback_check_pixmap(&pixmap->drawable)); -} - -inline static Bool glamor_is_large_pixmap(PixmapPtr pixmap) { glamor_pixmap_private *priv; priv = glamor_get_pixmap_private(pixmap); - return (priv->type == GLAMOR_TEXTURE_LARGE); -} - -inline static Bool -glamor_is_large_picture(PicturePtr picture) -{ - PixmapPtr pixmap; - - if (picture->pDrawable) { - pixmap = glamor_get_drawable_pixmap(picture->pDrawable); - return glamor_is_large_pixmap(pixmap); - } - return FALSE; -} - -inline static Bool -glamor_tex_format_is_readable(GLenum format) -{ - return ((format == GL_RGBA || format == GL_RGB || format == GL_ALPHA)); - + return (glamor_pixmap_priv_is_large(priv)); } static inline void _glamor_dump_pixmap_bits(PixmapPtr pixmap, int x, int y, int w, int h) { int i, j; - unsigned char *p = pixmap->devPrivate.ptr; - int stride = pixmap->devKind; + unsigned char *p = (pixmap)->devPrivate.ptr; + int stride = (pixmap)->devKind; p = p + y * stride + x; @@ -1023,8 +882,8 @@ static inline void _glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int w, int h) { int i, j; - unsigned char *p = pixmap->devPrivate.ptr; - int stride = pixmap->devKind; + unsigned char *p = (pixmap)->devPrivate.ptr; + int stride = (pixmap)->devKind; p = p + y * stride + x; @@ -1041,8 +900,8 @@ static inline void _glamor_dump_pixmap_sword(PixmapPtr pixmap, int x, int y, int w, int h) { int i, j; - unsigned short *p = pixmap->devPrivate.ptr; - int stride = pixmap->devKind / 2; + unsigned short *p = (pixmap)->devPrivate.ptr; + int stride = (pixmap)->devKind / 2; p = p + y * stride + x; @@ -1059,8 +918,8 @@ static inline void _glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int w, int h) { int i, j; - unsigned int *p = pixmap->devPrivate.ptr; - int stride = pixmap->devKind / 4; + unsigned int *p = (pixmap)->devPrivate.ptr; + int stride = (pixmap)->devKind / 4; p = p + y * stride + x; @@ -1076,11 +935,11 @@ _glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int w, int h) static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h) { - w = ((x + w) > pixmap->drawable.width) ? (pixmap->drawable.width - x) : w; - h = ((y + h) > pixmap->drawable.height) ? (pixmap->drawable.height - y) : h; + w = ((x + w) > (pixmap)->drawable.width) ? ((pixmap)->drawable.width - x) : w; + h = ((y + h) > (pixmap)->drawable.height) ? ((pixmap)->drawable.height - y) : h; - glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO); - switch (pixmap->drawable.depth) { + glamor_prepare_access(&(pixmap)->drawable, GLAMOR_ACCESS_RO); + switch ((pixmap)->drawable.depth) { case 8: _glamor_dump_pixmap_byte(pixmap, x, y, w, h); break; @@ -1097,9 +956,9 @@ glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h) _glamor_dump_pixmap_bits(pixmap, x, y, w, h); break; default: - ErrorF("dump depth %d, not implemented.\n", pixmap->drawable.depth); + ErrorF("dump depth %d, not implemented.\n", (pixmap)->drawable.depth); } - glamor_finish_access(&pixmap->drawable); + glamor_finish_access(&(pixmap)->drawable); } static inline void @@ -1297,7 +1156,7 @@ glamor_compare_pictures(ScreenPtr screen, GLAMOR_CREATE_PIXMAP_CPU); pixman_pic = CreatePicture(0, - &pixmap->drawable, + &(pixmap)->drawable, PictureMatchFormat(screen, PIXMAN_FORMAT_DEPTH (format), format), 0, 0, @@ -1325,7 +1184,7 @@ glamor_compare_pictures(ScreenPtr screen, GLAMOR_CREATE_PIXMAP_CPU); pixman_pic = CreatePicture(0, - &pixmap->drawable, + &(pixmap)->drawable, PictureMatchFormat(screen, PIXMAN_FORMAT_DEPTH (format), format), 0, 0, @@ -1345,9 +1204,9 @@ glamor_compare_pictures(ScreenPtr screen, if (fst_pixmap->drawable.depth != snd_pixmap->drawable.depth) { if (fst_generated) - glamor_destroy_picture(fst_picture); + miDestroyPicture(fst_picture); if (snd_generated) - glamor_destroy_picture(snd_picture); + miDestroyPicture(snd_picture); ErrorF("Different pixmap depth can not compare!\n"); return; @@ -1373,9 +1232,9 @@ glamor_compare_pictures(ScreenPtr screen, glamor_finish_access(&snd_pixmap->drawable); if (fst_generated) - glamor_destroy_picture(fst_picture); + miDestroyPicture(fst_picture); if (snd_generated) - glamor_destroy_picture(snd_picture); + miDestroyPicture(snd_picture); return; } @@ -1429,4 +1288,19 @@ glamor_make_current(glamor_screen_private *glamor_priv) } } +/** + * Helper function for implementing draws with GL_QUADS on GLES2, + * where we don't have them. + */ +static inline void +glamor_glDrawArrays_GL_QUADS(glamor_screen_private *glamor_priv, unsigned count) +{ + if (glamor_priv->use_quads) { + glDrawArrays(GL_QUADS, 0, count * 4); + } else { + glamor_gldrawarrays_quads_using_indices(glamor_priv, count); + } +} + + #endif diff --git a/xserver/glamor/glamor_vbo.c b/xserver/glamor/glamor_vbo.c index e90610102..b8db0092b 100644 --- a/xserver/glamor/glamor_vbo.c +++ b/xserver/glamor/glamor_vbo.c @@ -96,6 +96,15 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset) data = glamor_priv->vb + glamor_priv->vbo_offset; glamor_priv->vbo_offset += size; } else if (glamor_priv->has_map_buffer_range) { + /* Avoid GL errors on GL 4.5 / ES 3.0 with mapping size == 0, + * which callers may sometimes pass us (for example, if + * clipping leads to zero rectangles left). Prior to that + * version, Mesa would sometimes throw errors on unmapping a + * zero-size mapping. + */ + if (size == 0) + return NULL; + if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) { glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size); glamor_priv->vbo_offset = 0; @@ -109,9 +118,9 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset) GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT); - assert(data != NULL); *vbo_offset = (char *)(uintptr_t)glamor_priv->vbo_offset; glamor_priv->vbo_offset += size; + glamor_priv->vbo_mapped = TRUE; } else { /* Return a pointer to the statically allocated non-VBO * memory. We'll upload it through glBufferData() later. @@ -145,7 +154,10 @@ glamor_put_vbo_space(ScreenPtr screen) * reach the end of the buffer. */ } else if (glamor_priv->has_map_buffer_range) { - glUnmapBuffer(GL_ARRAY_BUFFER); + if (glamor_priv->vbo_mapped) { + glUnmapBuffer(GL_ARRAY_BUFFER); + glamor_priv->vbo_mapped = FALSE; + } } else { glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, glamor_priv->vb, GL_DYNAMIC_DRAW); @@ -162,6 +174,11 @@ glamor_init_vbo(ScreenPtr screen) glamor_make_current(glamor_priv); glGenBuffers(1, &glamor_priv->vbo); + if (glamor_priv->has_vertex_array_object) { + glGenVertexArrays(1, &glamor_priv->vao); + glBindVertexArray(glamor_priv->vao); + } else + glamor_priv->vao = 0; } void @@ -171,7 +188,10 @@ glamor_fini_vbo(ScreenPtr screen) glamor_make_current(glamor_priv); - glDeleteBuffers(1, &glamor_priv->vbo); + if (glamor_priv->vao != 0) { + glDeleteVertexArrays(1, &glamor_priv->vao); + glamor_priv->vao = 0; + } if (!glamor_priv->has_map_buffer_range) free(glamor_priv->vb); } diff --git a/xserver/glamor/glamor_window.c b/xserver/glamor/glamor_window.c index 60647bf80..5fd463b43 100644 --- a/xserver/glamor/glamor_window.c +++ b/xserver/glamor/glamor_window.c @@ -65,35 +65,3 @@ glamor_change_window_attributes(WindowPtr pWin, unsigned long mask) } return TRUE; } - -void -glamor_set_window_pixmap(WindowPtr win, PixmapPtr pPixmap) -{ - ScreenPtr screen = win->drawable.pScreen; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - PixmapPtr old = screen->GetWindowPixmap(win); - - if (pPixmap != old) { - glamor_pixmap_private *pixmap_priv; - PicturePtr pic = NULL; - - pixmap_priv = glamor_get_pixmap_private(old); - if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) && - pixmap_priv->base.picture->pDrawable == (DrawablePtr) win) { - pic = pixmap_priv->base.picture; - pixmap_priv->base.is_picture = 0; - pixmap_priv->base.picture = NULL; - } - - pixmap_priv = glamor_get_pixmap_private(pPixmap); - if (pixmap_priv) { - pixmap_priv->base.is_picture = ! !pic; - pixmap_priv->base.picture = pic; - } - } - - screen->SetWindowPixmap = glamor_priv->saved_procs.set_window_pixmap; - (screen->SetWindowPixmap) (win, pPixmap); - glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap; - screen->SetWindowPixmap = glamor_set_window_pixmap; -} diff --git a/xserver/glamor/glamor_xv.c b/xserver/glamor/glamor_xv.c index 83e24adb2..3bcf909b0 100644 --- a/xserver/glamor/glamor_xv.c +++ b/xserver/glamor/glamor_xv.c @@ -37,6 +37,8 @@ #endif #include "glamor_priv.h" +#include "glamor_transform.h" +#include "glamor_transfer.h" #include <X11/extensions/Xv.h> #include "../hw/xfree86/common/fourcc.h" @@ -57,36 +59,36 @@ typedef struct tagREF_TRANSFORM { #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0) #define RTFHue(a) (((a)*3.1416)/1000.0) -static const char *xv_vs = "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord0;\n" - "varying vec2 tcs;\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - "tcs = v_texcoord0.xy;\n" - "}\n"; - -static const char *xv_ps = GLAMOR_DEFAULT_PRECISION - "uniform sampler2D y_sampler;\n" - "uniform sampler2D u_sampler;\n" - "uniform sampler2D v_sampler;\n" - "uniform vec4 offsetyco;\n" - "uniform vec4 ucogamma;\n" - "uniform vec4 vco;\n" - "varying vec2 tcs;\n" - "float sample;\n" - "vec4 temp1;\n" - "void main()\n" - "{\n" - "sample = texture2D(y_sampler, tcs).w;\n" - "temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n" - "sample = texture2D(u_sampler, tcs).w;\n" - "temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n" - "sample = texture2D(v_sampler, tcs).w;\n" - "temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n" - "temp1.w = 1.0;\n" - "gl_FragColor = temp1;\n" - "}\n"; +static const glamor_facet glamor_facet_xv_planar = { + .name = "xv_planar", + + .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 sampler2D v_sampler;\n" + "uniform vec4 offsetyco;\n" + "uniform vec4 ucogamma;\n" + "uniform vec4 vco;\n" + "varying vec2 tcs;\n"), + .fs_exec = ( + " float sample;\n" + " vec4 temp1;\n" + " sample = texture2D(y_sampler, tcs).w;\n" + " temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n" + " sample = texture2D(u_sampler, tcs).w;\n" + " temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n" + " sample = texture2D(v_sampler, tcs).w;\n" + " temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n" + " temp1.w = 1.0;\n" + " gl_FragColor = temp1;\n" + ), +}; #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -112,23 +114,21 @@ int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images); static void glamor_init_xv_shader(ScreenPtr screen) { - glamor_screen_private *glamor_priv; - GLint fs_prog, vs_prog; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + GLint sampler_loc; + + glamor_build_program(screen, + &glamor_priv->xv_prog, + &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); - glamor_priv = glamor_get_screen_private(screen); - glamor_make_current(glamor_priv); - glamor_priv->xv_prog = glCreateProgram(); - - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xv_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xv_ps); - glAttachShader(glamor_priv->xv_prog, vs_prog); - glAttachShader(glamor_priv->xv_prog, fs_prog); - - glBindAttribLocation(glamor_priv->xv_prog, - GLAMOR_VERTEX_POS, "v_position"); - glBindAttribLocation(glamor_priv->xv_prog, - GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(screen, glamor_priv->xv_prog, "xv"); } #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) @@ -241,14 +241,11 @@ glamor_xv_render(glamor_port_private *port_priv) { ScreenPtr screen = port_priv->pPixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(port_priv->pPixmap); + PixmapPtr pixmap = port_priv->pPixmap; + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_pixmap_private *src_pixmap_priv[3]; - float vertices[32], texcoords[8]; BoxPtr box = REGION_RECTS(&port_priv->clip); int nBox = REGION_NUM_RECTS(&port_priv->clip); - int dst_x_off, dst_y_off; - GLfloat dst_xscale, dst_yscale; GLfloat src_xscale[3], src_yscale[3]; int i; const float Loff = -0.0627; @@ -258,9 +255,12 @@ glamor_xv_render(glamor_port_private *port_priv) float uco[3], vco[3], off[3]; float bright, cont, gamma; int ref = port_priv->transform_index; - GLint uloc, sampler_loc; + GLint uloc; + GLfloat *v; + char *vbo_offset; + int dst_box_index; - if (!glamor_priv->xv_prog) + if (!glamor_priv->xv_prog.prog) glamor_init_xv_shader(screen); cont = RTFContrast(port_priv->contrast); @@ -282,10 +282,7 @@ glamor_xv_render(glamor_port_private *port_priv) off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright; gamma = 1.0; - pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale); - glamor_get_drawable_deltas(port_priv->pDraw, port_priv->pPixmap, &dst_x_off, - &dst_y_off); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_set_alu(screen, GXcopy); for (i = 0; i < 3; i++) { if (port_priv->src_pix[i]) { @@ -296,90 +293,101 @@ glamor_xv_render(glamor_port_private *port_priv) } } glamor_make_current(glamor_priv); - glUseProgram(glamor_priv->xv_prog); + glUseProgram(glamor_priv->xv_prog.prog); - uloc = glGetUniformLocation(glamor_priv->xv_prog, "offsetyco"); + uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "offsetyco"); glUniform4f(uloc, off[0], off[1], off[2], yco); - uloc = glGetUniformLocation(glamor_priv->xv_prog, "ucogamma"); + uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "ucogamma"); glUniform4f(uloc, uco[0], uco[1], uco[2], gamma); - uloc = glGetUniformLocation(glamor_priv->xv_prog, "vco"); + uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "vco"); glUniform4f(uloc, vco[0], vco[1], vco[2], 0); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->base.fbo->tex); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->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); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->base.fbo->tex); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->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); glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->base.fbo->tex); + 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); - sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "y_sampler"); - glUniform1i(sampler_loc, 0); - sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "u_sampler"); - glUniform1i(sampler_loc, 1); - sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "v_sampler"); - glUniform1i(sampler_loc, 2); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + glEnable(GL_SCISSOR_TEST); + + v = glamor_get_vbo_space(screen, 3 * 4 * sizeof(GLfloat), &vbo_offset); + + /* 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 + * GL_QUAD. + */ + i = 0; + v[i++] = port_priv->drw_x; + v[i++] = port_priv->drw_y; + + v[i++] = port_priv->drw_x + port_priv->dst_w * 2; + v[i++] = port_priv->drw_y; + + v[i++] = port_priv->drw_x; + v[i++] = port_priv->drw_y + port_priv->dst_h * 2; + + v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x); + v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y); + + v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x + + port_priv->src_w * 2); + v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y); + + v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x); + v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y + + port_priv->src_h * 2); + + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, + GL_FLOAT, GL_FALSE, + 2 * sizeof(float), vbo_offset); glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), texcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + 2 * sizeof(float), vbo_offset + 6 * sizeof(GLfloat)); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), vertices); + glamor_put_vbo_space(screen); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glEnable(GL_SCISSOR_TEST); - for (i = 0; i < nBox; i++) { - float off_x = box[i].x1 - port_priv->drw_x; - float off_y = box[i].y1 - port_priv->drw_y; - float diff_x = (float) port_priv->src_w / (float) port_priv->dst_w; - float diff_y = (float) port_priv->src_h / (float) port_priv->dst_h; - float srcx, srcy, srcw, srch; - int dstx, dsty, dstw, dsth; - - dstx = box[i].x1 + dst_x_off; - dsty = box[i].y1 + dst_y_off; - dstw = box[i].x2 - box[i].x1; - dsth = box[i].y2 - box[i].y1; - - srcx = port_priv->src_x + off_x * diff_x; - srcy = port_priv->src_y + off_y * diff_y; - srcw = (port_priv->src_w * dstw) / (float) port_priv->dst_w; - srch = (port_priv->src_h * dsth) / (float) port_priv->dst_h; - - glamor_set_normalize_vcoords(pixmap_priv, - dst_xscale, dst_yscale, - dstx - dstw, - dsty, - dstx + dstw, - dsty + dsth * 2, - vertices); - - glamor_set_normalize_tcoords(src_pixmap_priv[0], - src_xscale[0], - src_yscale[0], - srcx - srcw, - srcy, - srcx + srcw, - srcy + srch * 2, - texcoords); - - glScissor(dstx, dsty, dstw, dsth); - glDrawArrays(GL_TRIANGLE_FAN, 0, 3); + /* Now draw our big triangle, clipped to each of the clip boxes. */ + glamor_pixmap_loop(pixmap_priv, dst_box_index) { + int dst_off_x, dst_off_y; + + glamor_set_destination_drawable(port_priv->pDraw, + dst_box_index, + FALSE, FALSE, + glamor_priv->xv_prog.matrix_uniform, + &dst_off_x, &dst_off_y); + + for (i = 0; i < nBox; i++) { + int dstx, dsty, dstw, dsth; + + dstx = box[i].x1 + dst_off_x; + dsty = box[i].y1 + dst_off_y; + dstw = box[i].x2 - box[i].x1; + dsth = box[i].y2 - box[i].y1; + + glScissor(dstx, dsty, dstw, dsth); + glDrawArrays(GL_TRIANGLE_FAN, 0, 3); + } } glDisable(GL_SCISSOR_TEST); @@ -409,6 +417,7 @@ glamor_xv_put_image(glamor_port_private *port_priv, int srcPitch, srcPitch2; int top, nlines; int s2offset, s3offset, tmp; + BoxRec full_box, half_box; s2offset = s3offset = srcPitch2 = 0; @@ -451,20 +460,28 @@ glamor_xv_put_image(glamor_port_private *port_priv, s2offset = s3offset; s3offset = tmp; } - glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0], - 0, 0, width, nlines, - srcPitch, - buf + (top * srcPitch), 0); - - glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1], - 0, 0, width >> 1, (nlines + 1) >> 1, - srcPitch2, - buf + s2offset, 0); - - glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2], - 0, 0, width >> 1, (nlines + 1) >> 1, - srcPitch2, - buf + s3offset, 0); + + 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 >> 1; + 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, srcPitch2); + + glamor_upload_boxes(port_priv->src_pix[2], &half_box, 1, + 0, 0, 0, 0, + buf + s3offset, srcPitch2); break; default: return BadMatch; @@ -478,7 +495,7 @@ glamor_xv_put_image(glamor_port_private *port_priv, RegionCopy(&port_priv->clip, clipBoxes); port_priv->src_x = src_x; - port_priv->src_y = src_y; + port_priv->src_y = src_y - top; port_priv->src_w = src_w; port_priv->src_h = src_h; port_priv->dst_w = drw_w; |