[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