[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