glamor: Replace CompositeGlyphs code [v2]
New composite glyphs code uses the updated glamor program infrastructure to create efficient shaders for drawing render text. Glyphs are cached in two atlases (one 8-bit, one 32-bit) in a simple linear fashion. When the atlas fills, it is discarded and a new one constructed. v2: Eric Anholt changed the non-GLSL 130 path to use quads instead of two triangles for a significant performance improvement on hardware with quads. Someone can fix the GLES quads emulation if they want to make it faster there. v3: Eric found more dead code to delete Signed-off-by: Keith Packard <keithp@keithp.com> Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
		
							parent
							
								
									1b745e0c1f
								
							
						
					
					
						commit
						b0d2e01031
					
				| 
						 | 
					@ -14,7 +14,7 @@ libglamor_la_SOURCES = \
 | 
				
			||||||
	glamor_font.c \
 | 
						glamor_font.c \
 | 
				
			||||||
	glamor_font.h \
 | 
						glamor_font.h \
 | 
				
			||||||
	glamor_glx.c \
 | 
						glamor_glx.c \
 | 
				
			||||||
	glamor_glyphs.c \
 | 
						glamor_composite_glyphs.c \
 | 
				
			||||||
	glamor_image.c \
 | 
						glamor_image.c \
 | 
				
			||||||
	glamor_lines.c \
 | 
						glamor_lines.c \
 | 
				
			||||||
	glamor_segs.c \
 | 
						glamor_segs.c \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -288,16 +288,6 @@ glamor_create_screen_resources(ScreenPtr screen)
 | 
				
			||||||
        ret = screen->CreateScreenResources(screen);
 | 
					        ret = screen->CreateScreenResources(screen);
 | 
				
			||||||
    screen->CreateScreenResources = glamor_create_screen_resources;
 | 
					    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;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -509,6 +499,11 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 | 
				
			||||||
    glamor_priv->saved_procs.block_handler = screen->BlockHandler;
 | 
					    glamor_priv->saved_procs.block_handler = screen->BlockHandler;
 | 
				
			||||||
    screen->BlockHandler = _glamor_block_handler;
 | 
					    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;
 | 
					    glamor_priv->saved_procs.create_gc = screen->CreateGC;
 | 
				
			||||||
    screen->CreateGC = glamor_create_gc;
 | 
					    screen->CreateGC = glamor_create_gc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -550,10 +545,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 | 
				
			||||||
    ps->CompositeRects = miCompositeRects;
 | 
					    ps->CompositeRects = miCompositeRects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glamor_priv->saved_procs.glyphs = ps->Glyphs;
 | 
					    glamor_priv->saved_procs.glyphs = ps->Glyphs;
 | 
				
			||||||
    ps->Glyphs = glamor_glyphs;
 | 
					    ps->Glyphs = glamor_composite_glyphs;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    glamor_priv->saved_procs.unrealize_glyph = ps->UnrealizeGlyph;
 | 
					 | 
				
			||||||
    ps->UnrealizeGlyph = glamor_glyph_unrealize;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glamor_priv->saved_procs.create_picture = ps->CreatePicture;
 | 
					    glamor_priv->saved_procs.create_picture = ps->CreatePicture;
 | 
				
			||||||
    ps->CreatePicture = glamor_create_picture;
 | 
					    ps->CreatePicture = glamor_create_picture;
 | 
				
			||||||
| 
						 | 
					@ -634,7 +626,7 @@ glamor_close_screen(ScreenPtr screen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glamor_priv = glamor_get_screen_private(screen);
 | 
					    glamor_priv = glamor_get_screen_private(screen);
 | 
				
			||||||
    glamor_sync_close(screen);
 | 
					    glamor_sync_close(screen);
 | 
				
			||||||
    glamor_glyphs_fini(screen);
 | 
					    glamor_composite_glyphs_fini(screen);
 | 
				
			||||||
    screen->CloseScreen = glamor_priv->saved_procs.close_screen;
 | 
					    screen->CloseScreen = glamor_priv->saved_procs.close_screen;
 | 
				
			||||||
    screen->CreateScreenResources =
 | 
					    screen->CreateScreenResources =
 | 
				
			||||||
        glamor_priv->saved_procs.create_screen_resources;
 | 
					        glamor_priv->saved_procs.create_screen_resources;
 | 
				
			||||||
| 
						 | 
					@ -655,7 +647,6 @@ glamor_close_screen(ScreenPtr screen)
 | 
				
			||||||
    ps->CreatePicture = glamor_priv->saved_procs.create_picture;
 | 
					    ps->CreatePicture = glamor_priv->saved_procs.create_picture;
 | 
				
			||||||
    ps->CompositeRects = glamor_priv->saved_procs.composite_rects;
 | 
					    ps->CompositeRects = glamor_priv->saved_procs.composite_rects;
 | 
				
			||||||
    ps->Glyphs = glamor_priv->saved_procs.glyphs;
 | 
					    ps->Glyphs = glamor_priv->saved_procs.glyphs;
 | 
				
			||||||
    ps->UnrealizeGlyph = glamor_priv->saved_procs.unrealize_glyph;
 | 
					 | 
				
			||||||
    screen->SetWindowPixmap = glamor_priv->saved_procs.set_window_pixmap;
 | 
					    screen->SetWindowPixmap = glamor_priv->saved_procs.set_window_pixmap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    screen_pixmap = screen->GetScreenPixmap(screen);
 | 
					    screen_pixmap = screen->GetScreenPixmap(screen);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,8 +105,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 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,
 | 
					extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap,
 | 
				
			||||||
                                                unsigned int tex);
 | 
					                                                unsigned int tex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,551 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (glyph_pixmap->drawable.bitsPerPixel == atlas_draw->bitsPerPixel) {
 | 
				
			||||||
 | 
					        glamor_upload_boxes((PixmapPtr) atlas_draw,
 | 
				
			||||||
 | 
					                            &box, 1,
 | 
				
			||||||
 | 
					                            0, 0,
 | 
				
			||||||
 | 
					                            x, y,
 | 
				
			||||||
 | 
					                            glyph_pixmap->devPrivate.ptr,
 | 
				
			||||||
 | 
					                            glyph_pixmap->devKind);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GCPtr scratch_gc = GetScratchGC(atlas_draw->depth, atlas_draw->pScreen);
 | 
				
			||||||
 | 
					        ChangeGCVal changes[2];
 | 
				
			||||||
 | 
					        if (!scratch_gc)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* If we're dealing with 1-bit glyphs, we upload them to
 | 
				
			||||||
 | 
					         * the cache as normal 8-bit alpha, since that's what GL
 | 
				
			||||||
 | 
					         * can handle.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        assert(glyph_draw->depth == 1);
 | 
				
			||||||
 | 
					        assert(atlas_draw->depth == 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        changes[0].val = 0xff;
 | 
				
			||||||
 | 
					        changes[1].val = 0x00;
 | 
				
			||||||
 | 
					        if (ChangeGC(NullClient, scratch_gc,
 | 
				
			||||||
 | 
					                     GCForeground|GCBackground, changes) != Success)
 | 
				
			||||||
 | 
					            goto bail_gc;
 | 
				
			||||||
 | 
					        ValidateGC(atlas_draw, scratch_gc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        (*scratch_gc->ops->CopyPlane)(glyph_draw,
 | 
				
			||||||
 | 
					                                      atlas_draw,
 | 
				
			||||||
 | 
					                                      scratch_gc,
 | 
				
			||||||
 | 
					                                      0, 0,
 | 
				
			||||||
 | 
					                                      glyph_draw->width,
 | 
				
			||||||
 | 
					                                      glyph_draw->height,
 | 
				
			||||||
 | 
					                                      x, y, 0x1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bail_gc:
 | 
				
			||||||
 | 
					        FreeScratchGC(scratch_gc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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, 0);
 | 
				
			||||||
 | 
					    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"),
 | 
				
			||||||
 | 
					    .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, 0);
 | 
				
			||||||
 | 
					    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
 | 
				
			||||||
 | 
					    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
 | 
				
			||||||
 | 
					    int box_x, box_y;
 | 
				
			||||||
 | 
					    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_x, box_y) {
 | 
				
			||||||
 | 
					            BoxPtr box = RegionRects(dst->pCompositeClip);
 | 
				
			||||||
 | 
					            int nbox = RegionNumRects(dst->pCompositeClip);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            glamor_set_destination_drawable(drawable, box_x, box_y, 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 * 4);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (prog->alpha != glamor_program_alpha_ca_first)
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        prog++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glDisable(GL_SCISSOR_TEST);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
 | 
				
			||||||
 | 
					    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
				
			||||||
 | 
					    glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					    PicturePtr glyph_pict = NULL;
 | 
				
			||||||
 | 
					    DrawablePtr glyph_draw;
 | 
				
			||||||
 | 
					    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) {
 | 
				
			||||||
 | 
					                glamor_pixmap_private *glyph_pix_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                glyph_pict = GlyphPicture(glyph)[screen_num];
 | 
				
			||||||
 | 
					                glyph_draw = glyph_pict->pDrawable;
 | 
				
			||||||
 | 
					                glyph_pix_priv = glamor_get_pixmap_private((PixmapPtr) glyph_draw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Need to draw with slow path?
 | 
				
			||||||
 | 
					                 */
 | 
				
			||||||
 | 
					                if (_X_UNLIKELY(glyph_draw->width > glyph_max_dim ||
 | 
				
			||||||
 | 
					                                glyph_draw->height > glyph_max_dim ||
 | 
				
			||||||
 | 
					                                (glyph_pix_priv != 0 && glyph_pix_priv->type != GLAMOR_MEMORY)))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    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);
 | 
				
			||||||
 | 
					                        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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -154,41 +154,8 @@ enum glamor_gl_flavor {
 | 
				
			||||||
    GLAMOR_GL_ES2               // OPENGL ES2.0 API
 | 
					    GLAMOR_GL_ES2               // OPENGL ES2.0 API
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define GLAMOR_COMPOSITE_VBO_VERT_CNT (64*1024)
 | 
					#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 {
 | 
					struct glamor_saved_procs {
 | 
				
			||||||
    CloseScreenProcPtr close_screen;
 | 
					    CloseScreenProcPtr close_screen;
 | 
				
			||||||
    CreateScreenResourcesProcPtr create_screen_resources;
 | 
					    CreateScreenResourcesProcPtr create_screen_resources;
 | 
				
			||||||
| 
						 | 
					@ -208,7 +175,6 @@ struct glamor_saved_procs {
 | 
				
			||||||
    AddTrapsProcPtr addtraps;
 | 
					    AddTrapsProcPtr addtraps;
 | 
				
			||||||
    CreatePictureProcPtr create_picture;
 | 
					    CreatePictureProcPtr create_picture;
 | 
				
			||||||
    DestroyPictureProcPtr destroy_picture;
 | 
					    DestroyPictureProcPtr destroy_picture;
 | 
				
			||||||
    UnrealizeGlyphProcPtr unrealize_glyph;
 | 
					 | 
				
			||||||
    SetWindowPixmapProcPtr set_window_pixmap;
 | 
					    SetWindowPixmapProcPtr set_window_pixmap;
 | 
				
			||||||
#if XSYNC
 | 
					#if XSYNC
 | 
				
			||||||
    SyncScreenFuncsRec sync_screen_funcs;
 | 
					    SyncScreenFuncsRec sync_screen_funcs;
 | 
				
			||||||
| 
						 | 
					@ -274,6 +240,14 @@ typedef struct glamor_screen_private {
 | 
				
			||||||
    glamor_program_fill on_off_dash_line_progs;
 | 
					    glamor_program_fill on_off_dash_line_progs;
 | 
				
			||||||
    glamor_program      double_dash_line_prog;
 | 
					    glamor_program      double_dash_line_prog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* vertext/elment_index buffer object for render */
 | 
					    /* vertext/elment_index buffer object for render */
 | 
				
			||||||
    GLuint vbo, ebo;
 | 
					    GLuint vbo, ebo;
 | 
				
			||||||
    /** Next offset within the VBO that glamor_get_vbo_space() will use. */
 | 
					    /** Next offset within the VBO that glamor_get_vbo_space() will use. */
 | 
				
			||||||
| 
						 | 
					@ -292,9 +266,6 @@ typedef struct glamor_screen_private {
 | 
				
			||||||
    glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT]
 | 
					    glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT]
 | 
				
			||||||
        [SHADER_MASK_COUNT]
 | 
					        [SHADER_MASK_COUNT]
 | 
				
			||||||
        [SHADER_IN_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;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* shaders to restore a texture to another texture. */
 | 
					    /* shaders to restore a texture to another texture. */
 | 
				
			||||||
    GLint finish_access_prog[2];
 | 
					    GLint finish_access_prog[2];
 | 
				
			||||||
| 
						 | 
					@ -707,17 +678,6 @@ RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
glamor_track_stipple(GCPtr gc);
 | 
					glamor_track_stipple(GCPtr gc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* glamor_glyphs.c */
 | 
					 | 
				
			||||||
Bool glamor_realize_glyph_caches(ScreenPtr screen);
 | 
					 | 
				
			||||||
void glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph);
 | 
					 | 
				
			||||||
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 */
 | 
					/* glamor_render.c */
 | 
				
			||||||
Bool glamor_composite_clipped_region(CARD8 op,
 | 
					Bool glamor_composite_clipped_region(CARD8 op,
 | 
				
			||||||
                                     PicturePtr source,
 | 
					                                     PicturePtr source,
 | 
				
			||||||
| 
						 | 
					@ -744,10 +704,6 @@ void glamor_composite(CARD8 op,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void glamor_init_composite_shaders(ScreenPtr screen);
 | 
					void glamor_init_composite_shaders(ScreenPtr screen);
 | 
				
			||||||
void glamor_fini_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,
 | 
					void glamor_composite_rects(CARD8 op,
 | 
				
			||||||
                            PicturePtr pDst,
 | 
					                            PicturePtr pDst,
 | 
				
			||||||
                            xRenderColor *color, int nRect, xRectangle *rects);
 | 
					                            xRenderColor *color, int nRect, xRectangle *rects);
 | 
				
			||||||
| 
						 | 
					@ -994,6 +950,22 @@ void glamor_composite_rectangles(CARD8 op,
 | 
				
			||||||
                                 xRenderColor *color,
 | 
					                                 xRenderColor *color,
 | 
				
			||||||
                                 int num_rects, xRectangle *rects);
 | 
					                                 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 */
 | 
					/* glamor_sync.c */
 | 
				
			||||||
Bool
 | 
					Bool
 | 
				
			||||||
glamor_sync_init(ScreenPtr screen);
 | 
					glamor_sync_init(ScreenPtr screen);
 | 
				
			||||||
| 
						 | 
					@ -1077,8 +1049,6 @@ void glamor_xv_render(glamor_port_private *port_priv);
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
#define MAX_FBO_SIZE 32         /* For test purpose only. */
 | 
					#define MAX_FBO_SIZE 32         /* For test purpose only. */
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
//#define GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK
 | 
					 | 
				
			||||||
#define GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "glamor_font.h"
 | 
					#include "glamor_font.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,6 +139,10 @@ static glamor_location_var location_vars[] = {
 | 
				
			||||||
        .vs_vars = "uniform float dash_length;\n",
 | 
					        .vs_vars = "uniform float dash_length;\n",
 | 
				
			||||||
        .fs_vars = "uniform sampler2D dash;\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])
 | 
					#define NUM_LOCATION_VARS       (sizeof location_vars / sizeof location_vars[0])
 | 
				
			||||||
| 
						 | 
					@ -355,6 +359,7 @@ glamor_build_program(ScreenPtr          screen,
 | 
				
			||||||
    prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul");
 | 
					    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_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->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(version_string);
 | 
				
			||||||
    free(fs_vars);
 | 
					    free(fs_vars);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,7 @@ struct _glamor_program {
 | 
				
			||||||
    GLint                       bitmul_uniform;
 | 
					    GLint                       bitmul_uniform;
 | 
				
			||||||
    GLint                       dash_uniform;
 | 
					    GLint                       dash_uniform;
 | 
				
			||||||
    GLint                       dash_length_uniform;
 | 
					    GLint                       dash_length_uniform;
 | 
				
			||||||
 | 
					    GLint                       atlas_uniform;
 | 
				
			||||||
    glamor_program_location     locations;
 | 
					    glamor_program_location     locations;
 | 
				
			||||||
    glamor_program_flag         flags;
 | 
					    glamor_program_flag         flags;
 | 
				
			||||||
    glamor_use                  prim_use;
 | 
					    glamor_use                  prim_use;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1701,139 +1701,3 @@ glamor_composite(CARD8 op,
 | 
				
			||||||
    glamor_finish_access_picture(source);
 | 
					    glamor_finish_access_picture(source);
 | 
				
			||||||
    glamor_finish_access_picture(dest);
 | 
					    glamor_finish_access_picture(dest);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
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))) {
 | 
					 | 
				
			||||||
        PixmapPtr src_pixmap = NULL;
 | 
					 | 
				
			||||||
        PixmapPtr mask_pixmap = NULL;
 | 
					 | 
				
			||||||
        PixmapPtr dst_pixmap = NULL;
 | 
					 | 
				
			||||||
        PixmapPtr temp_src_pixmap = NULL;
 | 
					 | 
				
			||||||
        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 = glamor_get_drawable_pixmap(dst->pDrawable);
 | 
					 | 
				
			||||||
        dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (mask && mask->pDrawable) {
 | 
					 | 
				
			||||||
            mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable);
 | 
					 | 
				
			||||||
            mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (src->pDrawable) {
 | 
					 | 
				
			||||||
            src_pixmap = glamor_get_drawable_pixmap(src->pDrawable);
 | 
					 | 
				
			||||||
            src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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_pixmap = (PixmapPtr) (temp_src->pDrawable);
 | 
					 | 
				
			||||||
            temp_src_priv = glamor_get_pixmap_private(temp_src_pixmap);
 | 
					 | 
				
			||||||
            glamor_composite_src_rect_translate(nrect, rects,
 | 
					 | 
				
			||||||
                                                -src_extent.x1, -src_extent.y1);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            temp_src = src;
 | 
					 | 
				
			||||||
            temp_src_pixmap = src_pixmap;
 | 
					 | 
				
			||||||
            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_pixmap, mask_pixmap, dst_pixmap,
 | 
					 | 
				
			||||||
                                                 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_pixmap, mask_pixmap, dst_pixmap,
 | 
					 | 
				
			||||||
                 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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue