[PATCH 13/20] glamor: Add glamor_program based copy acceleration

Markus Wick markus at selfnet.de
Wed Mar 19 07:48:20 PDT 2014


Am 2014-03-19 06:09, schrieb Keith Packard:
> Uses glCopyPixels for self-copies, otherwise paints with textures.
> Performs CPU to GPU transfers for pixmaps in memory.
> Accelerates copy plane when both objects are in memory
> Includes copy_window acceleration too.
> 
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
>  glamor/Makefile.am      |   1 +
>  glamor/glamor.c         |   2 +-
>  glamor/glamor_copy.c    | 510 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  glamor/glamor_core.c    |   4 +-
>  glamor/glamor_priv.h    |  30 +++
>  glamor/glamor_program.c |  10 +-
>  glamor/glamor_program.h |   3 +
>  7 files changed, 556 insertions(+), 4 deletions(-)
>  create mode 100644 glamor/glamor_copy.c
> 
> diff --git a/glamor/Makefile.am b/glamor/Makefile.am
> index f859155..7f756dc 100644
> --- a/glamor/Makefile.am
> +++ b/glamor/Makefile.am
> @@ -7,6 +7,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) 
> $(GLAMOR_CFLAGS)
>  libglamor_la_SOURCES = \
>  	glamor.c \
>  	glamor_context.h \
> +	glamor_copy.c \
>  	glamor_copyarea.c \
>  	glamor_copywindow.c \
>  	glamor_core.c \
> diff --git a/glamor/glamor.c b/glamor/glamor.c
> index dd18386..3117013 100644
> --- a/glamor/glamor.c
> +++ b/glamor/glamor.c
> @@ -439,7 +439,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
>          screen->ChangeWindowAttributes = 
> glamor_change_window_attributes;
> 
>          glamor_priv->saved_procs.copy_window = screen->CopyWindow;
> -        screen->CopyWindow = glamor_copy_window;
> +        screen->CopyWindow = glamor_copywindow;
> 
>          glamor_priv->saved_procs.bitmap_to_region = 
> screen->BitmapToRegion;
>          screen->BitmapToRegion = glamor_bitmap_to_region;
> diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c
> new file mode 100644
> index 0000000..a26c4a7
> --- /dev/null
> +++ b/glamor/glamor_copy.c
> @@ -0,0 +1,510 @@
> +/*
> + * 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 "glamor_priv.h"
> +#include "glamor_transfer.h"
> +#include "glamor_prepare.h"
> +#include "glamor_transform.h"
> +
> +struct copy_args {
> +    PixmapPtr           src_pixmap;
> +    glamor_pixmap_fbo   *src;
> +    uint32_t            bitplane;
> +    int                 dx, dy;
> +};
> +
> +static Bool
> +use_copyarea(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg)
> +{
> +    struct copy_args *args = arg;
> +    glamor_pixmap_fbo *src = args->src;
> +
> +    glActiveTexture(GL_TEXTURE0);
> +    glBindTexture(GL_TEXTURE_2D, src->tex);
> +
> +    glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
> +    glUniform2f(prog->fill_size_uniform, src->width, src->height);
> +
> +    return TRUE;
> +}
> +
> +static const glamor_facet glamor_facet_copyarea = {
> +    "copy_area",
> +    .version = 130,
> +    .vs_vars = "attribute vec4 primitive;\n",
> +    .vs_exec = ("       vec2 pos = (primitive.zw - primitive.xy) *
> vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
> +                GLAMOR_POS(gl_Position, (primitive.xy + pos))
> +                "       fill_pos = fill_offset + primitive.xy + 
> pos;\n"),
> +    .fs_exec = "       gl_FragColor = texelFetch(sampler,
> ivec2(fill_pos), 0);\n",
> +    .locations = glamor_program_location_fill,
> +    .use = use_copyarea,
> +};
> +
> +static Bool
> +use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void 
> *arg)
> +{
> +    struct copy_args *args = arg;
> +    glamor_pixmap_fbo *src = args->src;
> +
> +    glActiveTexture(GL_TEXTURE0);
> +    glBindTexture(GL_TEXTURE_2D, src->tex);
> +
> +    glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
> +    glUniform2f(prog->fill_size_uniform, src->width, src->height);
> +
> +    glamor_set_color(dst, gc->fgPixel, prog->fg_uniform);
> +    glamor_set_color(dst, gc->bgPixel, prog->bg_uniform);
> +
> +    /* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap
> private knows this? */
> +    switch (args->src_pixmap->drawable.depth) {
> +    case 24:
> +        glUniform4ui(prog->bitplane_uniform,
> +                     (args->bitplane >> 16) & 0xff,
> +                     (args->bitplane >>  8) & 0xff,
> +                     (args->bitplane      ) & 0xff,
> +                     0);
> +
> +        glUniform4ui(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0);
> +        break;
> +    case 32:
> +        glUniform4ui(prog->bitplane_uniform,
> +                     (args->bitplane >> 16) & 0xff,
> +                     (args->bitplane >>  8) & 0xff,
> +                     (args->bitplane      ) & 0xff,
> +                     (args->bitplane >> 24) & 0xff);
> +
> +        glUniform4ui(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0xff);
> +        break;
> +    case 16:
> +        glUniform4ui(prog->bitplane_uniform,
> +                     (args->bitplane >> 11) & 0x1f,
> +                     (args->bitplane >>  5) & 0x3f,
> +                     (args->bitplane      ) & 0x1f,
> +                     0);
> +
> +        glUniform4ui(prog->bitmul_uniform, 0x1f, 0x3f, 0x1f, 0);
> +        break;
> +    case 15:
> +        glUniform4ui(prog->bitplane_uniform,
> +                     (args->bitplane >> 10) & 0x1f,
> +                     (args->bitplane >>  5) & 0x1f,
> +                     (args->bitplane      ) & 0x1f,
> +                     0);
> +
> +        glUniform4ui(prog->bitmul_uniform, 0x1f, 0x1f, 0x1f, 0);
> +        break;
> +    case 8:
> +        glUniform4ui(prog->bitplane_uniform,
> +                     0, 0, 0, args->bitplane);
> +        glUniform4ui(prog->bitmul_uniform, 0, 0, 0, 0xff);
> +        break;
> +    case 1:
> +        glUniform4ui(prog->bitplane_uniform,
> +                     0, 0, 0, args->bitplane);
> +        glUniform4ui(prog->bitmul_uniform, 0, 0, 0, 0xff);
> +        break;
> +    }
> +
> +    return TRUE;
> +}
> +
> +static const glamor_facet glamor_facet_copyplane = {
> +    "copy_plane",
> +    .version = 130,
> +    .vs_vars = "attribute vec4 primitive;\n",
> +    .vs_exec = ("       vec2 pos = (primitive.zw - primitive.xy) *
> vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
> +                GLAMOR_POS(gl_Position, (primitive.xy + pos))
> +                "       fill_pos = fill_offset + primitive.xy + 
> pos;\n"),
> +    .fs_exec = ("       uvec4 bits = uvec4(texelFetch(sampler,
> ivec2(fill_pos), 0) * bitmul + vec4(0.5,0.5,0.5,0.5));\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,
> +    .use = use_copyplane,
> +};
> +
> +static void
> +glamor_copy_bail(DrawablePtr src,
> +                 DrawablePtr dst,
> +                 GCPtr gc,
> +                 BoxPtr box,
> +                 int nbox,
> +                 int dx,
> +                 int dy,
> +                 Bool reverse,
> +                 Bool upsidedown,
> +                 Pixel bitplane,
> +                 void *closure)
> +{
> +    if (glamor_prep_drawable(dst, TRUE) && glamor_prep_drawable(src, 
> FALSE)) {
> +        if (bitplane) {
> +            if (src->bitsPerPixel > 1)
> +                fbCopyNto1(src, dst, gc, box, nbox, dx, dy,
> +                           reverse, upsidedown, bitplane, closure);
> +            else
> +                fbCopy1toN(src, dst, gc, box, nbox, dx, dy,
> +                           reverse, upsidedown, bitplane, closure);
> +        } else {
> +            fbCopyNtoN(src, dst, gc, box, nbox, dx, dy,
> +                       reverse, upsidedown, bitplane, closure);
> +        }
> +    }
> +    glamor_fini_drawable(dst);
> +    glamor_fini_drawable(src);
> +}
> +
> +static void
> +glamor_copy_cpu_fbo(DrawablePtr src,
> +                    DrawablePtr dst,
> +                    GCPtr gc,
> +                    BoxPtr box,
> +                    int nbox,
> +                    int dx,
> +                    int dy,
> +                    Bool reverse,
> +                    Bool upsidedown,
> +                    Pixel bitplane,
> +                    void *closure)
> +{
> +    ScreenPtr screen = dst->pScreen;
> +    glamor_screen_private *glamor_priv = 
> glamor_get_screen_private(screen);
> +    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
> +    glamor_pixmap_private *dst_priv = 
> glamor_get_pixmap_private(dst_pixmap);
> +    FbBits *src_bits;
> +    FbStride src_stride;
> +    int src_bpp;
> +    int src_xoff, src_yoff;
> +    int dst_xoff, dst_yoff;
> +
> +    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv))
> +        goto bail;
> +
> +    if (gc && gc->alu != GXcopy)
> +        goto bail;
> +
> +    if (gc && !glamor_pm_is_solid(dst, gc->planemask))
> +        goto bail;
> +
> +    glamor_get_context(glamor_priv);
> +    glamor_prep_drawable(src, FALSE);
> +
> +    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff);
> +
> +    fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, 
> src_yoff);
> +
> +    glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff 
> + dy,
> +                        dst->x + dst_xoff, dst->y + dst_yoff,
> +                        (uint8_t *) src_bits, src_stride * sizeof 
> (FbBits));
> +    glamor_fini_drawable(src);
> +    glamor_put_context(glamor_priv);
> +
> +    return;
> +
> +bail:
> +    glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse,
> upsidedown, bitplane, closure);
> +}
> +
> +static void
> +glamor_copy_fbo_fbo(DrawablePtr src,
> +                    DrawablePtr dst,
> +                    GCPtr gc,
> +                    BoxPtr box,
> +                    int nbox,
> +                    int dx,
> +                    int dy,
> +                    Bool reverse,
> +                    Bool upsidedown,
> +                    Pixel bitplane,
> +                    void *closure)

You haven't used reverse, upsidedown and closure. Aren't they needed?

> +{
> +    ScreenPtr screen = dst->pScreen;
> +    glamor_screen_private *glamor_priv = 
> glamor_get_screen_private(screen);
> +    PixmapPtr src_pixmap = glamor_get_drawable_pixmap(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 b;
> +    Bool use_copy_pixels = FALSE;
> +
> +    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv) ||
> !GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv))
> +        goto bail;
> +
> +    glamor_get_context(glamor_priv);
> +
> +    if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask))
> +        goto bail_ctx;
> +
> +    if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
> +        goto bail_ctx;
> +
> +    if (src_pixmap == dst_pixmap) {
> +        if (bitplane)
> +            goto bail_ctx;
> +        use_copy_pixels = TRUE;
> +    }
> +
> +    if (use_copy_pixels) {
> +        static float modelview[16] = {
> +            1, 0, 0, 0,
> +            0, 1, 0, 0,
> +            0, 0, 1, 0,
> +            -1, -1, 0, 1,
> +        };
> +
> +        glMatrixMode(GL_PROJECTION);
> +        glLoadIdentity();
> +
> +        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);
> +            glBindFramebuffer(GL_READ_FRAMEBUFFER,
> glamor_pixmap_fbo_at(src_priv, src_box_x, src_box_y)->fb);
> +
> +            glamor_pixmap_loop(dst_priv, dst_box_x, dst_box_y) {
> +                BoxPtr dst_box = glamor_pixmap_box_at(dst_priv,
> dst_box_x, dst_box_y);
> +
> +                glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> glamor_pixmap_fbo_at(dst_priv, dst_box_x, dst_box_y)->fb);
> +                glViewport(0, 0, dst_box->x2 - dst_box->x1,
> dst_box->y2 - dst_box->y1);
> +
> +                glMatrixMode(GL_MODELVIEW);
> +
> +                modelview[0] = 2.0f / (dst_box->x2 - dst_box->x1);
> +                modelview[5] = 2.0f / (dst_box->y2 - dst_box->y1);
> +
> +                glLoadMatrixf(modelview);
> +
> +                for (b = 0; b < nbox; b++) {
> +                    int     dx1, dx2, dy1, dy2;
> +
> +                    dx1 = box[b].x1;
> +                    dx2 = box[b].x2;
> +
> +                    dy1 = box[b].y1;
> +                    dy2 = box[b].y2;
> +
> +                    /* clip to the destination box */
> +                    if (dx1 < dst_box->x1)
> +                        dx1 = dst_box->x1;
> +                    if (dst_box->x2 < dx2)
> +                        dx2 = dst_box->x2;
> +
> +                    if (dy1 < dst_box->y1)
> +                        dy1 = dst_box->y1;
> +                    if (dst_box->y2 < dy2)
> +                        dy2 = dst_box->y2;
> +
> +                    /* clip to the source box */
> +
> +                    if (dx1 < src_box->x1 - dx)
> +                        dx1 = src_box->x1 - dx;
> +                    if (src_box->x2 - dx < dx2)
> +                        dx2 = src_box->x2 - dx;
> +
> +                    if (dy1 < src_box->y1 - dy)
> +                        dy1 = src_box->y1 - dy;
> +                    if (src_box->y2 - dy < dy2)
> +                        dy2 = src_box->y2 - dy;
> +
> +                    if (dx1 >= dx2)
> +                        continue;
> +                    if (dy1 >= dy2)
> +                        continue;
> +
> +
> +                    glRasterPos2i(dx1 - dst_box->x1, dy1 - 
> dst_box->y1);
> +                    glCopyPixels (dx1 + dx - src_box->x1,
> +                                  dy1 + dy - src_box->y1,
> +                                  dx2 - dx1, dy2 - dy1, GL_COLOR);

This functions are deprecated fortunately. Please don't use them at all.
Glamor shall be used as hardware accelerated fallback, so we shouldn't 
rely on uncommon features which may be implemented in software (eg on 
nvidia) or not implemented at all (core, gles).
I guess you want to use this to get a defined result for overlapping 
rects? Bad luck, this call is also undefined:
   18.3.1 Copying Pixel Rectangles
   Undefined pixel values result from overlapping copies
   http://www.opengl.org/registry/doc/glspec44.compatibility.pdf

I see two ways to handle overlapping copys:
- Emit lots of non-overlapping draw calls / blits / copys
- Create a temporary buffer and copy twice

I guess GPUs have some special HW for this, but we can't use them on 
OpenGL. memmove isn't parallelizable.

> +                }
> +            }
> +        }
> +    } else {
> +
> +        int dst_off_x, dst_off_y;
> +        int src_off_x, src_off_y;
> +        GLshort *v;
> +        char *vbo_offset;
> +        struct copy_args args;
> +        glamor_program *prog;
> +        const glamor_facet *copy_facet;
> +        Bool set_scissor;
> +
> +        if (bitplane) {
> +            prog = &glamor_priv->copy_plane_prog;
> +            copy_facet = &glamor_facet_copyplane;
> +        } else {
> +            prog = &glamor_priv->copy_area_prog;
> +            copy_facet = &glamor_facet_copyarea;
> +        }
> +
> +        if (prog->failed)
> +            goto bail_ctx;
> +
> +        if (!prog->prog) {
> +            if (!glamor_build_program(screen, prog,
> +                                      copy_facet, NULL))
> +                goto bail_ctx;
> +        }
> +
> +        args.src_pixmap = src_pixmap;
> +        args.bitplane = bitplane;
> +
> +        /* Set up the vertex buffers for the points */
> +
> +        v = glamor_get_vbo_space(dst->pScreen, nbox * (4 * sizeof
> (GLshort)), &vbo_offset);
> +
> +        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
> +        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
> +        glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, 
> GL_FALSE,
> +                              4 * sizeof (GLshort), vbo_offset);
> +
> +        memcpy(v, box, nbox * sizeof (BoxRec));
> +
> +        glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, 
> &src_off_y);
> +
> +        glamor_put_vbo_space(screen);
> +
> +        set_scissor = src_priv->type == GLAMOR_TEXTURE_LARGE;
> +        if (set_scissor)
> +            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);
> +
> +            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);
> +
> +            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);
> +
> +                glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nbox);

Do you think it's worth to add a fast path with glBlitframebuffer or 
glCopyImageSubData?
Both should have a better GPU performance and glCopyImageSubData should 
also have a lower CPU overhead.

> +            }
> +        }
> +        if (set_scissor)
> +            glDisable(GL_SCISSOR_TEST);
> +        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
> +        glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
> +    }
> +
> +    glDisable(GL_COLOR_LOGIC_OP);
> +    glamor_put_context(glamor_priv);
> +    return;
> +
> +bail_ctx:
> +    glDisable(GL_COLOR_LOGIC_OP);
> +    glamor_put_context(glamor_priv);
> +bail:
> +    glamor_copy_bail(src, dst, gc, box, nbox, dx, dy,
> +                     reverse, upsidedown, bitplane, closure);
> +}
> +
> +void
> +glamor_copy(DrawablePtr src,
> +            DrawablePtr dst,
> +            GCPtr gc,
> +            BoxPtr box,
> +            int nbox,
> +            int dx,
> +            int dy,
> +            Bool reverse,
> +            Bool upsidedown,
> +            Pixel bitplane,
> +            void *closure)
> +{
> +    PixmapPtr src_pixmap = glamor_get_drawable_pixmap(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);
> +
> +    if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv)) {
> +        if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv)) {
> +            glamor_copy_fbo_fbo(src, dst, gc, box, nbox, dx, dy,
> reverse, upsidedown, bitplane, closure);
> +            return;
> +        }
> +        if (bitplane == 0) {
> +            glamor_copy_cpu_fbo(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);
> +}
> +
> +RegionPtr
> +glamor_copyarea(DrawablePtr src, DrawablePtr dst, GCPtr gc,
> +                int srcx, int srcy, int width, int height, int dstx, 
> int dsty)
> +{
> +    return miDoCopy(src, dst, gc,
> +                    srcx, srcy, width, height,
> +                    dstx, dsty, glamor_copy, 0, NULL);
> +}
> +
> +RegionPtr
> +glamor_copyplane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
> +                 int srcx, int srcy, int width, int height, int dstx, 
> int dsty,
> +                 unsigned long bitplane)
> +{
> +    if ((bitplane & FbFullMask(src->depth)) == 0)
> +        return miHandleExposures(src, dst, gc,
> +                                 srcx, srcy, width, height, dstx, 
> dsty,
> +                                 bitplane);
> +    return miDoCopy(src, dst, gc,
> +                    srcx, srcy, width, height,
> +                    dstx, dsty, glamor_copy, bitplane, NULL);
> +}
> +
> +void
> +glamor_copywindow(WindowPtr window, DDXPointRec old_origin, RegionPtr
> src_region)
> +{
> +    PixmapPtr pixmap = glamor_get_drawable_pixmap(&window->drawable);
> +    DrawablePtr drawable = &pixmap->drawable;
> +    RegionRec dst_region;
> +    int dx, dy;
> +
> +    dx = old_origin.x - window->drawable.x;
> +    dy = old_origin.y - window->drawable.y;
> +    RegionTranslate(src_region, -dx, -dy);
> +
> +    RegionNull(&dst_region);
> +
> +    RegionIntersect(&dst_region, &window->borderClip, src_region);
> +
> +#ifdef COMPOSITE
> +    if (pixmap->screen_x || pixmap->screen_y)
> +        RegionTranslate(&dst_region, -pixmap->screen_x, 
> -pixmap->screen_y);
> +#endif
> +
> +    miCopyRegion(drawable, drawable,
> +                 0, &dst_region, dx, dy, glamor_copy, 0, 0);
> +
> +    RegionUninit(&dst_region);
> +}
> diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
> index 23ac1b2..f350746 100644
> --- a/glamor/glamor_core.c
> +++ b/glamor/glamor_core.c
> @@ -416,8 +416,8 @@ GCOps glamor_gc_ops = {
>      .FillSpans = glamor_fillspans,
>      .SetSpans = glamor_setspans,
>      .PutImage = glamor_put_image,
> -    .CopyArea = glamor_copy_area,
> -    .CopyPlane = glamor_copy_plane,
> +    .CopyArea = glamor_copyarea,
> +    .CopyPlane = glamor_copyplane,
>      .PolyPoint = glamor_poly_point,
>      .Polylines = glamor_poly_lines,
>      .PolySegment = glamor_poly_segment,
> diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
> index 5df60ac..c0fd096 100644
> --- a/glamor/glamor_priv.h
> +++ b/glamor/glamor_priv.h
> @@ -233,6 +233,10 @@ typedef struct glamor_screen_private {
>      glamor_program      te_text_prog;
>      glamor_program      image_text_prog;
> 
> +    /* glamor copy shaders */
> +    glamor_program      copy_area_prog;
> +    glamor_program      copy_plane_prog;
> +
>      /* vertext/elment_index buffer object for render */
>      GLuint vbo, ebo;
>      /** Next offset within the VBO that glamor_get_vbo_space() will 
> use. */
> @@ -1017,6 +1021,32 @@ void
>  glamor_polyfillrect(DrawablePtr drawable,
>                      GCPtr gc, int nrect, xRectangle *prect);
> 
> +/* glamor_copy.c */
> +void
> +glamor_copy(DrawablePtr src,
> +            DrawablePtr dst,
> +            GCPtr gc,
> +            BoxPtr box,
> +            int nbox,
> +            int dx,
> +            int dy,
> +            Bool reverse,
> +            Bool upsidedown,
> +            Pixel bitplane,
> +            void *closure);
> +
> +RegionPtr
> +glamor_copyarea(DrawablePtr src, DrawablePtr dst, GCPtr gc,
> +                int srcx, int srcy, int width, int height, int dstx, 
> int dsty);
> +
> +RegionPtr
> +glamor_copyplane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
> +                 int srcx, int srcy, int width, int height, int dstx, 
> int dsty,
> +                 unsigned long bitplane);
> +
> +void
> +glamor_copywindow(WindowPtr window, DDXPointRec old_origin, RegionPtr
> src_region);
> +
>  /* glamor_glyphblt.c */
>  void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
>                              int x, int y, unsigned int nglyph,
> diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
> index 0f9b248..f7d795f 100644
> --- a/glamor/glamor_program.c
> +++ b/glamor/glamor_program.c
> @@ -117,6 +117,11 @@ static glamor_location_var location_vars[] = {
>          .location = glamor_program_location_font,
>          .fs_vars = "uniform usampler2D font;\n",
>      },
> +    {
> +        .location = glamor_program_location_bitplane,
> +        .fs_vars = ("uniform uvec4 bitplane;\n"
> +                    "uniform uvec4 bitmul;\n"),
> +    },
>  };
> 
>  #define NUM_LOCATION_VARS       (sizeof location_vars / sizeof
> location_vars[0])
> @@ -196,6 +201,8 @@ static const glamor_facet facet_null_fill = {
>      .name = ""
>  };
> 
> +#define DBG 0
> +
>  static GLint
>  glamor_get_uniform(glamor_program               *prog,
>                     glamor_program_location      location,
> @@ -289,7 +296,6 @@ glamor_build_program(ScreenPtr          screen,
>      if (!vs_prog_string || !fs_prog_string)
>          goto fail;
> 
> -#define DBG 0
>  #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);
> @@ -326,6 +332,8 @@ glamor_build_program(ScreenPtr          screen,
>      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->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");
> 
>      if (glGetError() != GL_NO_ERROR)
>          goto fail;
> diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
> index 88efc35..118f978 100644
> --- a/glamor/glamor_program.h
> +++ b/glamor/glamor_program.h
> @@ -29,6 +29,7 @@ typedef enum {
>      glamor_program_location_bg = 2,
>      glamor_program_location_fill = 4,
>      glamor_program_location_font = 8,
> +    glamor_program_location_bitplane = 16,
>  } glamor_program_location;
> 
>  typedef enum {
> @@ -61,6 +62,8 @@ struct _glamor_program {
>      GLint                       fill_size_uniform;
>      GLint                       fill_offset_uniform;
>      GLint                       font_uniform;
> +    GLint                       bitplane_uniform;
> +    GLint                       bitmul_uniform;
>      glamor_program_location     locations;
>      glamor_program_flag         flags;
>      glamor_use                  prim_use;


More information about the xorg-devel mailing list