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

Markus Wick markus at selfnet.de
Fri Mar 14 03:12:05 PDT 2014


First, I like to have some common functions to compile our shaders, bind 
common uniforms, defining common headers, ...
But tbh I don't see why it's easier to split up the glsl source 
completely. Most shaders aren't more than 5 loc, so they are easier to 
read entirely.
In dolphin, we've a common glsl "header" which is prepended for every 
shader and all common functions are defined there. Wouldn't such a 
"framework" be enough?

Am 2014-03-14 07:29, schrieb Keith Packard:
> diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
> new file mode 100644
> index 0000000..b0d4ff0
> --- /dev/null
> +++ b/glamor/glamor_program.c
> @@ -0,0 +1,422 @@
> +/*
> + * 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)
> +{
> +    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)
> +{
> +    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,
> +};
> +
> +#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,
> +};
> +
> +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";
> +
> +static const char *
> +str(const char *s)
> +{
> +    if (!s)
> +        return "";
> +    return s;
> +}
> +
> +Bool
> +glamor_build_program(ScreenPtr          screen,
> +                     glamor_program     *prog,
> +                     const glamor_facet *prim,
> +                     const glamor_facet *fill)
> +{
> +    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;
> +
> +    locations |= fill->locations;
> +    flags |= fill->flags;
> +    if (fill->version > version)
> +        version = fill->version;
> +
> +    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
> +
> +    (void) glGetError();
> +
> +    prog->prog = glCreateProgram();
> +    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);
> +    glAttachShader(prog->prog, 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 = glGetUniformLocation(prog->prog, 
> "v_matrix");
> +#if DBG
> +    ErrorF("matrix uniform %d\n", prog->matrix_uniform);
> +#endif
> +
> +    if (locations & glamor_program_location_fg) {
> +        prog->fg_uniform = glGetUniformLocation(prog->prog, "fg");
> +#if DBG
> +        ErrorF("fg uniform %d\n", prog->fg_uniform);
> +#endif
> +    }
> +
> +    if (locations & glamor_program_location_bg) {
> +        prog->bg_uniform = glGetUniformLocation(prog->prog, "bg");
> +#if DBG
> +        ErrorF("bg uniform %d\n", prog->bg_uniform);
> +#endif
> +    }
> +
> +    if (locations & glamor_program_location_fill) {
> +        prog->fill_offset_uniform = glGetUniformLocation(prog->prog,
> "fill_offset");
> +        prog->fill_size_uniform = glGetUniformLocation(prog->prog,
> "fill_size");
> +#if DBG
> +        ErrorF("fill offset uniform %d fill size uniform %d\n",
> +               prog->fill_offset_uniform, prog->fill_size_uniform);
> +#endif
> +    }
> +
> +    if (locations & glamor_program_location_font) {
> +        prog->font_uniform = glGetUniformLocation(prog->prog, "font");
> +#if DBG
> +        ErrorF("font uniform %d\n", prog->font_uniform);
> +#endif
> +    }
> +
> +    if (glGetError() != GL_NO_ERROR)
> +        goto fail;
> +
> +    prog->prim_use = prim->use;
> +    prog->fill_use = fill->use;
> +
> +    prog->flags = flags;
> +    prog->locations = locations;
> +
> +    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)
> +{
> +    glUseProgram(prog->prog);
> +
> +    if (prog->prim_use && !prog->prim_use(pixmap, gc, prog))
> +        return FALSE;
> +
> +    if (prog->fill_use && !prog->fill_use(pixmap, gc, prog))
> +        return FALSE;
> +
> +    return TRUE;
> +}
> +
> +glamor_program *
> +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))
> +        return NULL;
> +
> +    return prog;
> +}
> +
> +static void
> +glamor_delete_programs(ScreenPtr        screen,
> +                       glamor_program   *programs,
> +                       int              n)
> +{
> +    glamor_screen_private *glamor_priv;
> +    int i;
> +
> +    glamor_priv = glamor_get_screen_private(screen);
> +    glamor_get_context(glamor_priv);
> +    for (i = 0; i < n; i++) {
> +        glamor_program *prog = &programs[i];
> +        if (prog->prog)
> +            glDeleteProgram(prog->prog);
> +        memset(prog, '\0', sizeof (*prog));
> +    }
> +    glamor_put_context(glamor_priv);
> +}
> +
> +void
> +glamor_delete_program(ScreenPtr         screen,
> +                      glamor_program    *program)
> +{
> +    glamor_delete_programs(screen, program, 1);
> +}
> +
> +void
> +glamor_delete_program_fill(ScreenPtr            screen,
> +                           glamor_program_fill  *program_fill)
> +{
> +    glamor_delete_programs(screen, program_fill->progs, sizeof
> (program_fill->progs) / sizeof (program_fill->progs[0]));
> +}
> diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
> new file mode 100644
> index 0000000..6f920b4
> --- /dev/null
> +++ b/glamor/glamor_program.h
> @@ -0,0 +1,101 @@
> +/*
> + * 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);
> +
> +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);
> +
> +glamor_program *
> +glamor_use_program_fill(PixmapPtr               pixmap,
> +                        GCPtr                   gc,
> +                        glamor_program_fill     *program_fill,
> +                        const glamor_facet      *prim);
> +
> +void
> +glamor_delete_program(ScreenPtr         screen,
> +                      glamor_program    *program);
> +
> +void
> +glamor_delete_program_fill(ScreenPtr            screen,
> +                           glamor_program_fill  *program_fill);
> +
> +#endif /* _GLAMOR_PROGRAM_H_ */
> diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c
> new file mode 100644
> index 0000000..7ad6d8e
> --- /dev/null
> +++ b/glamor/glamor_transform.c
> @@ -0,0 +1,206 @@
> +/*
> + * 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,
> +                                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;
> +
> +    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;
> +    }
> +
> +    /* 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 does hurt. Points must be placed on pixel center, but polygon 
border on pixel center is undefined behavoir.
Hopefully we won't render lines. I guess for horizontal lines, x must be 
on pixel border and y on pixel center...

> +     *
> +     * 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;
> +    }
> +
> +    glUniform4f(matrix_uniform_location,
> +                scale_x, (off_x + 0.5f) * scale_x -1.0f,
> +                scale_y, (off_y + 0.5f) * 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;
> +}
> +
> +static Bool
> +glamor_set_texture(PixmapPtr    pixmap,
> +                   GCPtr        gc,
> +                   PixmapPtr    texture,
> +                   GLint        offset_uniform,
> +                   GLint        size_uniform)
> +{
> +    glamor_pixmap_private *texture_priv;
> +    int off_x, off_y;
> +
> +    texture_priv = glamor_get_pixmap_private(texture);
> +
> +    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv))
> +        return FALSE;
> +
> +    glActiveTexture(GL_TEXTURE0);
> +    glBindTexture(GL_TEXTURE_2D, texture_priv->base.fbo->tex);
> +
> +    off_x = gc->patOrg.x;
> +    off_y = gc->patOrg.y;
> +    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, gc->tile.pixmap,
> 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, gc->stipple, 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..d1cfbf9
> --- /dev/null
> +++ b/glamor/glamor_transform.h
> @@ -0,0 +1,78 @@
> +/*
> + * 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,
> +                                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_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