[PATCH 06/20] glamor: Add infrastructure for generating shaders on the fly

Markus Wick markus at selfnet.de
Wed Mar 19 04:09:12 PDT 2014


Am 2014-03-19 06:09, schrieb Keith Packard:
> This just adds a bunch of support code to construct shaders from
> 'facets', which bundle attributes needed for each layer of the
> rendering system. At this point, that includes only the primtive and
> the fill stuff.
> 
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
>  glamor/Makefile.am        |   2 +
>  glamor/glamor_priv.h      |   1 +
>  glamor/glamor_program.c   | 394 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  glamor/glamor_program.h   |  94 +++++++++++
>  glamor/glamor_transform.c | 216 +++++++++++++++++++++++++
>  glamor/glamor_transform.h |  87 ++++++++++
>  6 files changed, 794 insertions(+)
>  create mode 100644 glamor/glamor_program.c
>  create mode 100644 glamor/glamor_program.h
>  create mode 100644 glamor/glamor_transform.c
>  create mode 100644 glamor/glamor_transform.h
> 
> diff --git a/glamor/Makefile.am b/glamor/Makefile.am
> index ffc8c23..dec6467 100644
> --- a/glamor/Makefile.am
> +++ b/glamor/Makefile.am
> @@ -22,6 +22,8 @@ libglamor_la_SOURCES = \
>  	glamor_setspans.c \
>  	glamor_render.c \
>  	glamor_gradient.c \
> +	glamor_program.c \
> +	glamor_transform.c \
>  	glamor_trapezoid.c \
>  	glamor_tile.c \
>  	glamor_triangles.c\
> diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
> index fc9ab9e..5013799 100644
> --- a/glamor/glamor_priv.h
> +++ b/glamor/glamor_priv.h
> @@ -52,6 +52,7 @@
> 
>  #include "glamor_debug.h"
>  #include "glamor_context.h"
> +#include "glamor_program.h"
> 
>  #include <list.h>
> 
> diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
> new file mode 100644
> index 0000000..0f9b248
> --- /dev/null
> +++ b/glamor/glamor_program.c
> @@ -0,0 +1,394 @@
> +/*
> + * 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_transform.h"
> +#include "glamor_program.h"
> +
> +static Bool
> +use_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
> +{
> +    return glamor_set_solid(pixmap, gc, TRUE, prog->fg_uniform);
> +}
> +
> +const glamor_facet glamor_fill_solid = {
> +    .name = "solid",
> +    .fs_exec = "       gl_FragColor = fg;\n",
> +    .locations = glamor_program_location_fg,
> +    .use = use_solid,
> +};
> +
> +static Bool
> +use_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
> +{
> +    return glamor_set_tiled(pixmap, gc, prog->fill_offset_uniform,
> prog->fill_size_uniform);
> +}
> +
> +static const glamor_facet glamor_fill_tile = {
> +    .name = "tile",
> +    .version = 130,
> +    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + 
> pos;\n",
> +    .fs_exec =  "       gl_FragColor = texelFetch(sampler,
> ivec2(mod(fill_pos,fill_size)), 0);\n",
> +    .locations = glamor_program_location_fill,
> +    .use = use_tile,
> +};

I think it's better to access gl_FragCoord, so you don't have to add a 
new varying.

> +
> +#if 0
> +static Bool
> +use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog)
> +{
> +    return glamor_set_stippled(pixmap, gc, prog->fg_uniform,
> prog->fill_offset_uniform, prog->fill_size_uniform);
> +}
> +
> +static const glamor_facet glamor_fill_stipple = {
> +    .name = "stipple",
> +    .version = 130,
> +    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + 
> pos;\n";
> +    .fs_exec = ("       if (texelFetch(sampler,
> ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
> +                "               discard;\n"
> +                "       gl_FragColor = fg;\n")
> +    .locations = glamor_program_location_fg | 
> glamor_program_location_fill
> +    .use = use_stipple,
> +};
> +
> +static const glamor_facet glamor_fill_opaque_stipple = {
> +    .name = "opaque_stipple",
> +    .version = 130,
> +    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + 
> pos;\n";
> +    .fs_exec = ("       if (texelFetch(sampler,
> ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
> +                "               gl_FragColor = bg;\n"
> +                "       else\n"
> +                "               gl_FragColor = fg;\n"),
> +    .locations = glamor_program_location_fg |
> glamor_program_location_bg | glamor_program_location_fill
> +    .use = use_opaque_stipple
> +};
> +#endif
> +
> +static const glamor_facet *glamor_facet_fill[4] = {
> +    &glamor_fill_solid,
> +    &glamor_fill_tile,
> +    NULL,
> +    NULL,
> +};

I guess this 4 shaders are the basic ones for all of the legacy x11 
calls. But they aren't part of your facet based programm compilation 
framework. So I'd move them into a different file to not making this 
framework more confusing as necessary.

> +
> +typedef struct {
> +    glamor_program_location     location;
> +    const char                  *vs_vars;
> +    const char                  *fs_vars;
> +} glamor_location_var;
> +
> +static glamor_location_var location_vars[] = {
> +    {
> +        .location = glamor_program_location_fg,
> +        .fs_vars = "uniform vec4 fg;\n"
> +    },
> +    {
> +        .location = glamor_program_location_bg,
> +        .fs_vars = "uniform vec4 bg;\n"
> +    },
> +    {
> +        .location = glamor_program_location_fill,
> +        .vs_vars = ("uniform vec2 fill_offset;\n"
> +                    "varying vec2 fill_pos;\n"),
> +        .fs_vars = ("uniform sampler2D sampler;\n"
> +                    "uniform vec2 fill_size;\n"
> +                    "varying vec2 fill_pos;\n")
> +    },
> +    {
> +        .location = glamor_program_location_font,
> +        .fs_vars = "uniform usampler2D font;\n",
> +    },
> +};
> +
> +#define NUM_LOCATION_VARS       (sizeof location_vars / sizeof
> location_vars[0])
> +
> +static char *
> +add_var(char *cur, const char *add)
> +{
> +    char *new;
> +
> +    if (!add)
> +        return cur;
> +
> +    new = realloc(cur, strlen(cur) + strlen(add) + 1);
> +    if (!new) {
> +        free(cur);
> +        return NULL;
> +    }
> +    strcat(new, add);
> +    return new;
> +}
> +
> +static char *
> +vs_location_vars(glamor_program_location locations)
> +{
> +    int l;
> +    char *vars = strdup("");
> +
> +    for (l = 0; vars && l < NUM_LOCATION_VARS; l++)
> +        if (locations & location_vars[l].location)
> +            vars = add_var(vars, location_vars[l].vs_vars);
> +    return vars;
> +}
> +
> +static char *
> +fs_location_vars(glamor_program_location locations)
> +{
> +    int l;
> +    char *vars = strdup("");
> +
> +    for (l = 0; vars && l < NUM_LOCATION_VARS; l++)
> +        if (locations & location_vars[l].location)
> +            vars = add_var(vars, location_vars[l].fs_vars);
> +    return vars;
> +}
> +
> +static const char vs_template[] =
> +    "%s"                                /* version */
> +    "%s"                                /* prim vs_vars */
> +    "%s"                                /* fill vs_vars */
> +    "%s"                                /* location vs_vars */
> +    GLAMOR_DECLARE_MATRIX
> +    "void main() {\n"
> +    "%s"                                /* prim vs_exec, outputs
> 'pos' and gl_Position */
> +    "%s"                                /* fill vs_exec */
> +    "}\n";
> +
> +static const char fs_template[] =
> +    "%s"                                /* version */
> +    GLAMOR_DEFAULT_PRECISION
> +    "%s"                                /* prim fs_vars */
> +    "%s"                                /* fill fs_vars */
> +    "%s"                                /* location fs_vars */
> +    "void main() {\n"
> +    "%s"                                /* prim fs_exec */
> +    "%s"                                /* fill fs_exec */
> +    "}\n";

glShaderSource allows you to use an array of strings, so you don't have 
to concat them in such a way.

> +
> +static const char *
> +str(const char *s)
> +{
> +    if (!s)
> +        return "";
> +    return s;
> +}
> +
> +static const glamor_facet facet_null_fill = {
> +    .name = ""
> +};
> +
> +static GLint
> +glamor_get_uniform(glamor_program               *prog,
> +                   glamor_program_location      location,
> +                   const char                   *name)
> +{
> +    GLint uniform;
> +    if (location && (prog->locations & location) == 0)
> +        return -2;
> +    uniform = glGetUniformLocation(prog->prog, name);
> +#if DBG
> +    ErrorF("%s uniform %d\n", name, uniform);
> +#endif
> +    return uniform;
> +}
> +
> +Bool
> +glamor_build_program(ScreenPtr          screen,
> +                     glamor_program     *prog,
> +                     const glamor_facet *prim,
> +                     const glamor_facet *fill)
> +{
> +    glamor_screen_private *glamor_priv = 
> glamor_get_screen_private(screen);
> +
> +    glamor_program_location     locations = prim->locations;
> +    glamor_program_flag         flags = prim->flags;
> +
> +    int                         version = prim->version;
> +    char                        *version_string = NULL;
> +
> +    char                        *fs_vars = NULL;
> +    char                        *vs_vars = NULL;
> +
> +    char                        *vs_prog_string;
> +    char                        *fs_prog_string;
> +
> +    GLint                       fs_prog, vs_prog;
> +
> +    if (!fill)
> +        fill = &facet_null_fill;
> +
> +    locations |= fill->locations;
> +    flags |= fill->flags;
> +    version = MAX(version, fill->version);
> +
> +    if (version >= 130) {
> +
> +        /* Would be nice to have a cleaner test for GLSL 1.30 support,
> +         * but for now this should suffice
> +         */
> +        if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP ||
> +            glamor_gl_get_version() < GLAMOR_GL_VERSION_ENCODE(3, 0)) 
> {
> +            goto fail;
> +        }
> +    }
> +
> +    vs_vars = vs_location_vars(locations);
> +    fs_vars = fs_location_vars(locations);
> +
> +    if (!vs_vars)
> +        goto fail;
> +    if (!fs_vars)
> +        goto fail;
> +
> +    if (version) {
> +        if (asprintf(&version_string, "#version %d\n", version) < 0)
> +            version_string = NULL;
> +        if (!version_string)
> +            goto fail;
> +    }
> +
> +    if (asprintf(&vs_prog_string,
> +                 vs_template,
> +                 str(version_string),
> +                 str(prim->vs_vars),
> +                 str(fill->vs_vars),
> +                 vs_vars,
> +                 str(prim->vs_exec),
> +                 str(fill->vs_exec)) < 0)
> +        vs_prog_string = NULL;
> +
> +    if (asprintf(&fs_prog_string,
> +                 fs_template,
> +                 str(version_string),
> +                 str(prim->fs_vars),
> +                 str(fill->fs_vars),
> +                 fs_vars,
> +                 str(prim->fs_exec),
> +                 str(fill->fs_exec)) < 0)
> +        fs_prog_string = NULL;
> +
> +    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);
> +#endif
> +
> +    prog->prog = glCreateProgram();
> +    prog->flags = flags;
> +    prog->locations = locations;
> +    prog->prim_use = prim->use;
> +    prog->fill_use = fill->use;
> +
> +    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, 
> vs_prog_string);
> +    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, 
> fs_prog_string);
> +    free(vs_prog_string);
> +    free(fs_prog_string);
> +    glAttachShader(prog->prog, vs_prog);
> +    glDeleteShader(vs_prog);
> +    glAttachShader(prog->prog, fs_prog);
> +    glDeleteShader(fs_prog);
> +    glBindAttribLocation(prog->prog, GLAMOR_VERTEX_POS, "primitive");
> +
> +    if (prim->source_name) {
> +#if DBG
> +        ErrorF("Bind GLAMOR_VERTEX_SOURCE to %s\n", 
> prim->source_name);
> +#endif
> +        glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE,
> prim->source_name);
> +    }
> +
> +    glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, 
> fill->name);
> +
> +    prog->matrix_uniform = glamor_get_uniform(prog,
> glamor_program_location_none, "v_matrix");
> +    prog->fg_uniform = glamor_get_uniform(prog,
> glamor_program_location_fg, "fg");
> +    prog->bg_uniform = glamor_get_uniform(prog,
> glamor_program_location_bg, "bg");
> +    prog->fill_offset_uniform = glamor_get_uniform(prog,
> glamor_program_location_fill, "fill_offset");
> +    prog->fill_size_uniform = glamor_get_uniform(prog,
> glamor_program_location_fill, "fill_size");
> +    prog->font_uniform = glamor_get_uniform(prog,
> glamor_program_location_font, "font");
> +
> +    if (glGetError() != GL_NO_ERROR)
> +        goto fail;
> +
> +    free(version_string);
> +    free(fs_vars);
> +    free(vs_vars);
> +    return TRUE;
> +fail:
> +    prog->failed = 1;
> +    if (prog->prog) {
> +        glDeleteProgram(prog->prog);
> +        prog->prog = 0;
> +    }
> +    free(version_string);
> +    free(fs_vars);
> +    free(vs_vars);
> +    return FALSE;
> +}
> +
> +Bool
> +glamor_use_program(PixmapPtr            pixmap,
> +                   GCPtr                gc,
> +                   glamor_program       *prog,
> +                   void                 *arg)
> +{
> +    glUseProgram(prog->prog);
> +
> +    if (prog->prim_use && !prog->prim_use(pixmap, gc, prog, arg))
> +        return FALSE;
> +
> +    if (prog->fill_use && !prog->fill_use(pixmap, gc, prog, arg))
> +        return FALSE;
> +
> +    return TRUE;
> +}
> +
> +glamor_program *

Do you use this program anywhere but in other util functions? So I'd 
favor to store the current bound program in the screen state and just 
return a boolean.

> +glamor_use_program_fill(PixmapPtr               pixmap,
> +                        GCPtr                   gc,
> +                        glamor_program_fill     *program_fill,
> +                        const glamor_facet      *prim)
> +{
> +    ScreenPtr                   screen = pixmap->drawable.pScreen;
> +    glamor_program              *prog = 
> &program_fill->progs[gc->fillStyle];
> +
> +    int                         fill_style = gc->fillStyle;
> +    const glamor_facet          *fill;
> +
> +    if (prog->failed)
> +        return FALSE;
> +
> +    if (!prog->prog) {
> +        fill = glamor_facet_fill[fill_style];
> +        if (!fill)
> +            return NULL;
> +
> +        if (!glamor_build_program(screen, prog, prim, fill))
> +            return NULL;
> +    }
> +
> +    if (!glamor_use_program(pixmap, gc, prog, NULL))
> +        return NULL;
> +
> +    return prog;
> +}
> diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
> new file mode 100644
> index 0000000..88efc35
> --- /dev/null
> +++ b/glamor/glamor_program.h
> @@ -0,0 +1,94 @@
> +/*
> + * 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.
> + */
> +
> +#ifndef _GLAMOR_PROGRAM_H_
> +#define _GLAMOR_PROGRAM_H_
> +
> +typedef enum {
> +    glamor_program_location_none = 0,
> +    glamor_program_location_fg = 1,
> +    glamor_program_location_bg = 2,
> +    glamor_program_location_fill = 4,
> +    glamor_program_location_font = 8,
> +} glamor_program_location;
> +
> +typedef enum {
> +    glamor_program_flag_none = 0,
> +} glamor_program_flag;
> +
> +typedef struct _glamor_program glamor_program;
> +
> +typedef Bool (*glamor_use) (PixmapPtr pixmap, GCPtr gc,
> glamor_program *prog, void *arg);
> +
> +typedef struct {
> +    const char                          *name;
> +    const int                           version;
> +    const char                          *vs_vars;
> +    const char                          *vs_exec;
> +    const char                          *fs_vars;
> +    const char                          *fs_exec;
> +    const glamor_program_location       locations;
> +    const glamor_program_flag           flags;
> +    const char                          *source_name;
> +    glamor_use                          use;
> +} glamor_facet;
> +
> +struct _glamor_program {
> +    GLint                       prog;
> +    GLint                       failed;
> +    GLint                       matrix_uniform;
> +    GLint                       fg_uniform;
> +    GLint                       bg_uniform;
> +    GLint                       fill_size_uniform;
> +    GLint                       fill_offset_uniform;
> +    GLint                       font_uniform;
> +    glamor_program_location     locations;
> +    glamor_program_flag         flags;
> +    glamor_use                  prim_use;
> +    glamor_use                  fill_use;
> +};
> +
> +typedef struct {
> +    glamor_program      progs[4];
> +} glamor_program_fill;
> +
> +extern const glamor_facet glamor_fill_solid;
> +
> +Bool
> +glamor_build_program(ScreenPtr          screen,
> +                     glamor_program     *prog,
> +                     const glamor_facet *prim,
> +                     const glamor_facet *fill);
> +
> +Bool
> +glamor_use_program(PixmapPtr            pixmap,
> +                   GCPtr                gc,
> +                   glamor_program       *prog,
> +                   void                 *arg);
> +
> +glamor_program *
> +glamor_use_program_fill(PixmapPtr               pixmap,
> +                        GCPtr                   gc,
> +                        glamor_program_fill     *program_fill,
> +                        const glamor_facet      *prim);
> +
> +#endif /* _GLAMOR_PROGRAM_H_ */
> diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c
> new file mode 100644
> index 0000000..f5a6bb2
> --- /dev/null
> +++ b/glamor/glamor_transform.c
> @@ -0,0 +1,216 @@
> +/*
> + * 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_transform.h"
> +
> +
> +/*
> + * Set up rendering to target the specified drawable, computing an
> + * appropriate transform for the vertex shader to convert
> + * drawable-relative coordinates into pixmap-relative coordinates. If
> + * requested, the offset from pixmap origin coordinates back to window
> + * system coordinates will be returned in *p_off_x, *p_off_y so that
> + * clipping computations can be adjusted as appropriate
> + */
> +
> +void
> +glamor_set_destination_drawable(DrawablePtr     drawable,
> +                                int             box_x,
> +                                int             box_y,
> +                                Bool            do_drawable_translate,
> +                                Bool            center_offset,
> +                                GLint           
> matrix_uniform_location,
> +                                int             *p_off_x,
> +                                int             *p_off_y)
> +{
> +    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
> +    glamor_pixmap_private *pixmap_priv = 
> glamor_get_pixmap_private(pixmap);
> +    int off_x, off_y;
> +    BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y);
> +    int w = box->x2 - box->x1;
> +    int h = box->y2 - box->y1;
> +    float scale_x = 2.0f / (float) w;
> +    float scale_y = 2.0f / (float) h;
> +    float center_adjust = 0.0f;
> +
> +    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
> +
> +    off_x -= box->x1;
> +    off_y -= box->y1;
> +
> +    if (p_off_x) {
> +        *p_off_x = off_x;
> +        *p_off_y = off_y;
> +    }

I also think that we won't ask for only one of them, but it shouldn't 
crash if p_off_y is NULL but p_off_x isn't.

> +
> +    /* A tricky computation to find the right value for the two
> linear functions
> +     * that transform rendering coordinates to pixmap coordinates
> +     *
> +     *  pixmap_x = render_x + drawable->x + off_x
> +     *  pixmap_y = render_y + drawable->y + off_y
> +     *
> +     *  gl_x = pixmap_x * 2 / width - 1
> +     *  gl_y = pixmap_y * 2 / height - 1
> +     *
> +     *  gl_x = (render_x + drawable->x + off_x) * 2 / width - 1
> +     *
> +     *  gl_x = (render_x) * 2 / width + (drawable->x + off_x) * 2 / 
> width - 1
> +     *
> +     * To get GL_POINTS drawn in the right spot, we need to adjust the
> +     * coordinates by 1/2 a pixel. This doesn't hurt rectangles at
> +     * all, so we just always do it. If we need to change someday, we
> +     * can add a parameter to this function

This comment is outdated.

> +     *
> +     * I'll think about yInverted later, when I have some way to test
> +     */
> +
> +    if (do_drawable_translate) {
> +        off_x += drawable->x;
> +        off_y += drawable->y;
> +    }
> +
> +    if (center_offset)
> +        center_adjust = 0.5f;
> +
> +    glUniform4f(matrix_uniform_location,
> +                scale_x, (off_x + center_adjust) * scale_x - 1.0f,
> +                scale_y, (off_y + center_adjust) * scale_y - 1.0f);
> +
> +
> glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo_at(pixmap_priv,
> box_x, box_y),
> +                                      0, 0, w, h);
> +}
> +
> +/*
> + * Set up for solid rendering to the specified pixmap using alu, fg
> and planemask
> + * from the specified GC. Load the target color into the specified 
> uniform
> + */
> +
> +void
> +glamor_set_color(PixmapPtr      pixmap,
> +                 CARD32         pixel,
> +                 GLint          uniform)
> +{
> +    float       color[4];
> +
> +    glamor_get_rgba_from_pixel(pixel,
> +                               &color[0], &color[1], &color[2], 
> &color[3],
> +                               format_for_pixmap(pixmap));
> +
> +    glUniform4fv(uniform, 1, color);
> +}
> +
> +Bool
> +glamor_set_solid(PixmapPtr      pixmap,
> +                 GCPtr          gc,
> +                 Bool           use_alu,
> +                 GLint          uniform)
> +{
> +    CARD32      pixel;
> +    int         alu = use_alu ? gc->alu : GXcopy;
> +
> +    if (!glamor_set_planemask(pixmap, gc->planemask))
> +        return FALSE;
> +
> +    pixel = gc->fgPixel;
> +
> +    if (!glamor_set_alu(pixmap->drawable.pScreen, alu)) {
> +        switch (gc->alu) {
> +        case GXclear:
> +            pixel = 0;
> +            break;
> +        case GXcopyInverted:
> +            pixel = ~pixel;
> +            break;
> +        case GXset:
> +            pixel = ~0 & gc->planemask;
> +            break;
> +        default:
> +            return FALSE;
> +        }
> +    }
> +    glamor_set_color(pixmap, gc->fgPixel, uniform);
> +
> +    return TRUE;
> +}
> +
> +Bool
> +glamor_set_texture(PixmapPtr    pixmap,
> +                   PixmapPtr    texture,
> +                   int          off_x,
> +                   int          off_y,
> +                   GLint        offset_uniform,
> +                   GLint        size_uniform)
> +{
> +    glamor_pixmap_private *texture_priv;
> +
> +    texture_priv = glamor_get_pixmap_private(texture);
> +
> +    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv))
> +        return FALSE;
> +
> +    if (texture_priv->type == GLAMOR_TEXTURE_LARGE)
> +        return FALSE;
> +
> +    glActiveTexture(GL_TEXTURE0);
> +    glBindTexture(GL_TEXTURE_2D, texture_priv->base.fbo->tex);
> +
> +    glUniform2f(offset_uniform, off_x, off_y);
> +    glUniform2f(size_uniform, texture->drawable.width,
> texture->drawable.height);
> +    return TRUE;
> +}
> +
> +Bool
> +glamor_set_tiled(PixmapPtr      pixmap,
> +                 GCPtr          gc,
> +                 GLint          offset_uniform,
> +                 GLint          size_uniform)
> +{
> +    if (!glamor_set_alu(pixmap->drawable.pScreen, gc->alu))
> +        return FALSE;
> +
> +    if (!glamor_set_planemask(pixmap, gc->planemask))
> +        return FALSE;
> +
> +    return glamor_set_texture(pixmap,
> +                              gc->tile.pixmap,
> +                              gc->patOrg.x,
> +                              gc->patOrg.y,
> +                              offset_uniform,
> +                              size_uniform);
> +}
> +
> +Bool
> +glamor_set_stippled(PixmapPtr      pixmap,
> +                    GCPtr          gc,
> +                    GLint          fg_uniform,
> +                    GLint          offset_uniform,
> +                    GLint          size_uniform)
> +{
> +    if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
> +        return FALSE;
> +
> +    if (!glamor_set_texture(pixmap, gc->stipple, gc->patOrg.x,
> gc->patOrg.y, offset_uniform, size_uniform))
> +        return FALSE;
> +
> +    return TRUE;
> +}
> diff --git a/glamor/glamor_transform.h b/glamor/glamor_transform.h
> new file mode 100644
> index 0000000..36b789a
> --- /dev/null
> +++ b/glamor/glamor_transform.h
> @@ -0,0 +1,87 @@
> +/*
> + * 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.
> + */
> +
> +#ifndef _GLAMOR_TRANSFORM_H_
> +#define _GLAMOR_TRANSFORM_H_
> +
> +void
> +glamor_set_destination_drawable(DrawablePtr     drawable,
> +                                int             box_x,
> +                                int             box_y,
> +                                Bool            do_drawable_translate,
> +                                Bool            center_offset,
> +                                GLint           
> matrix_uniform_location,
> +                                int             *p_off_x,
> +                                int             *p_off_y);
> +
> +void
> +glamor_set_color(PixmapPtr      pixmap,
> +                 CARD32         pixel,
> +                 GLint          uniform);
> +
> +Bool
> +glamor_set_texture(PixmapPtr    pixmap,
> +                   PixmapPtr    texture,
> +                   int          off_x,
> +                   int          off_y,
> +                   GLint        offset_uniform,
> +                   GLint        size_uniform);
> +
> +Bool
> +glamor_set_solid(PixmapPtr      pixmap,
> +                 GCPtr          gc,
> +                 Bool           use_alu,
> +                 GLint          uniform);
> +
> +Bool
> +glamor_set_tiled(PixmapPtr      pixmap,
> +                 GCPtr          gc,
> +                 GLint          offset_uniform,
> +                 GLint          size_uniform);
> +
> +Bool
> +glamor_set_stippled(PixmapPtr      pixmap,
> +                    GCPtr          gc,
> +                    GLint          fg_uniform,
> +                    GLint          offset_uniform,
> +                    GLint          size_uniform);
> +
> +/*
> + * Vertex shader bits that transform X coordinates to pixmap
> + * coordinates using the matrix computed above
> + */
> +
> +#define GLAMOR_DECLARE_MATRIX   "uniform vec4 v_matrix;\n"
> +#define GLAMOR_X_POS(x) #x " *v_matrix.x + v_matrix.y"
> +#define GLAMOR_Y_POS(y) #y " *v_matrix.z + v_matrix.w"
> +#if 0
> +#define GLAMOR_POS(dst,src) \
> +    "       " #dst ".x = " #src ".x * v_matrix.x + v_matrix.y;\n" \
> +    "       " #dst ".y = " #src ".y * v_matrix.z + v_matrix.w;\n" \
> +    "       " #dst ".z = 0.0;\n" \
> +    "       " #dst ".w = 1.0;\n"
> +#endif
> +#define GLAMOR_POS(dst,src) \
> +    "       " #dst ".xy = " #src ".xy * v_matrix.xz + v_matrix.yw;\n" 
> \
> +    "       " #dst ".zw = vec2(0.0,1.0);\n"
> +
> +#endif /* _GLAMOR_TRANSFORM_H_ */


More information about the xorg-devel mailing list