135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2014 Keith Packard 335c4bbdfSmrg * 435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its 535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that 635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright 735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and 835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or 935c4bbdfSmrg * publicity pertaining to distribution of the software without specific, 1035c4bbdfSmrg * written prior permission. The copyright holders make no representations 1135c4bbdfSmrg * about the suitability of this software for any purpose. It is provided "as 1235c4bbdfSmrg * is" without express or implied warranty. 1335c4bbdfSmrg * 1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2035c4bbdfSmrg * OF THIS SOFTWARE. 2135c4bbdfSmrg */ 2235c4bbdfSmrg 2335c4bbdfSmrg#include "glamor_priv.h" 2435c4bbdfSmrg#include "glamor_transform.h" 2535c4bbdfSmrg#include "glamor_program.h" 2635c4bbdfSmrg 2735c4bbdfSmrgstatic Bool 2835c4bbdfSmrguse_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) 2935c4bbdfSmrg{ 3035c4bbdfSmrg return glamor_set_solid(pixmap, gc, TRUE, prog->fg_uniform); 3135c4bbdfSmrg} 3235c4bbdfSmrg 3335c4bbdfSmrgconst glamor_facet glamor_fill_solid = { 3435c4bbdfSmrg .name = "solid", 3535c4bbdfSmrg .fs_exec = " gl_FragColor = fg;\n", 3635c4bbdfSmrg .locations = glamor_program_location_fg, 3735c4bbdfSmrg .use = use_solid, 3835c4bbdfSmrg}; 3935c4bbdfSmrg 4035c4bbdfSmrgstatic Bool 4135c4bbdfSmrguse_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) 4235c4bbdfSmrg{ 4335c4bbdfSmrg return glamor_set_tiled(pixmap, gc, prog->fill_offset_uniform, prog->fill_size_inv_uniform); 4435c4bbdfSmrg} 4535c4bbdfSmrg 4635c4bbdfSmrgstatic const glamor_facet glamor_fill_tile = { 4735c4bbdfSmrg .name = "tile", 4835c4bbdfSmrg .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", 4935c4bbdfSmrg .fs_exec = " gl_FragColor = texture2D(sampler, fill_pos);\n", 5035c4bbdfSmrg .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos, 5135c4bbdfSmrg .use = use_tile, 5235c4bbdfSmrg}; 5335c4bbdfSmrg 5435c4bbdfSmrgstatic Bool 5535c4bbdfSmrguse_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) 5635c4bbdfSmrg{ 5735c4bbdfSmrg return glamor_set_stippled(pixmap, gc, prog->fg_uniform, 5835c4bbdfSmrg prog->fill_offset_uniform, 5935c4bbdfSmrg prog->fill_size_inv_uniform); 6035c4bbdfSmrg} 6135c4bbdfSmrg 6235c4bbdfSmrgstatic const glamor_facet glamor_fill_stipple = { 6335c4bbdfSmrg .name = "stipple", 6435c4bbdfSmrg .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", 6535c4bbdfSmrg .fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n" 6635c4bbdfSmrg " if (a == 0.0)\n" 6735c4bbdfSmrg " discard;\n" 6835c4bbdfSmrg " gl_FragColor = fg;\n"), 6935c4bbdfSmrg .locations = glamor_program_location_fg | glamor_program_location_fillsamp | glamor_program_location_fillpos, 7035c4bbdfSmrg .use = use_stipple, 7135c4bbdfSmrg}; 7235c4bbdfSmrg 7335c4bbdfSmrgstatic Bool 7435c4bbdfSmrguse_opaque_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) 7535c4bbdfSmrg{ 7635c4bbdfSmrg if (!use_stipple(pixmap, gc, prog, arg)) 7735c4bbdfSmrg return FALSE; 7835c4bbdfSmrg glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform); 7935c4bbdfSmrg return TRUE; 8035c4bbdfSmrg} 8135c4bbdfSmrg 8235c4bbdfSmrgstatic const glamor_facet glamor_fill_opaque_stipple = { 8335c4bbdfSmrg .name = "opaque_stipple", 8435c4bbdfSmrg .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", 8535c4bbdfSmrg .fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n" 8635c4bbdfSmrg " if (a == 0.0)\n" 8735c4bbdfSmrg " gl_FragColor = bg;\n" 8835c4bbdfSmrg " else\n" 8935c4bbdfSmrg " gl_FragColor = fg;\n"), 9035c4bbdfSmrg .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fillsamp | glamor_program_location_fillpos, 9135c4bbdfSmrg .use = use_opaque_stipple 9235c4bbdfSmrg}; 9335c4bbdfSmrg 9435c4bbdfSmrgstatic const glamor_facet *glamor_facet_fill[4] = { 9535c4bbdfSmrg &glamor_fill_solid, 9635c4bbdfSmrg &glamor_fill_tile, 9735c4bbdfSmrg &glamor_fill_stipple, 9835c4bbdfSmrg &glamor_fill_opaque_stipple, 9935c4bbdfSmrg}; 10035c4bbdfSmrg 10135c4bbdfSmrgtypedef struct { 10235c4bbdfSmrg glamor_program_location location; 10335c4bbdfSmrg const char *vs_vars; 10435c4bbdfSmrg const char *fs_vars; 10535c4bbdfSmrg} glamor_location_var; 10635c4bbdfSmrg 10735c4bbdfSmrgstatic glamor_location_var location_vars[] = { 10835c4bbdfSmrg { 10935c4bbdfSmrg .location = glamor_program_location_fg, 11035c4bbdfSmrg .fs_vars = "uniform vec4 fg;\n" 11135c4bbdfSmrg }, 11235c4bbdfSmrg { 11335c4bbdfSmrg .location = glamor_program_location_bg, 11435c4bbdfSmrg .fs_vars = "uniform vec4 bg;\n" 11535c4bbdfSmrg }, 11635c4bbdfSmrg { 11735c4bbdfSmrg .location = glamor_program_location_fillsamp, 11835c4bbdfSmrg .fs_vars = "uniform sampler2D sampler;\n" 11935c4bbdfSmrg }, 12035c4bbdfSmrg { 12135c4bbdfSmrg .location = glamor_program_location_fillpos, 12235c4bbdfSmrg .vs_vars = ("uniform vec2 fill_offset;\n" 12335c4bbdfSmrg "uniform vec2 fill_size_inv;\n" 12435c4bbdfSmrg "varying vec2 fill_pos;\n"), 1251b5d61b8Smrg .fs_vars = ("varying vec2 fill_pos;\n") 12635c4bbdfSmrg }, 12735c4bbdfSmrg { 12835c4bbdfSmrg .location = glamor_program_location_font, 12935c4bbdfSmrg .fs_vars = "uniform usampler2D font;\n", 13035c4bbdfSmrg }, 13135c4bbdfSmrg { 13235c4bbdfSmrg .location = glamor_program_location_bitplane, 13335c4bbdfSmrg .fs_vars = ("uniform uvec4 bitplane;\n" 13435c4bbdfSmrg "uniform vec4 bitmul;\n"), 13535c4bbdfSmrg }, 13635c4bbdfSmrg { 13735c4bbdfSmrg .location = glamor_program_location_dash, 13835c4bbdfSmrg .vs_vars = "uniform float dash_length;\n", 13935c4bbdfSmrg .fs_vars = "uniform sampler2D dash;\n", 14035c4bbdfSmrg }, 14135c4bbdfSmrg { 14235c4bbdfSmrg .location = glamor_program_location_atlas, 14335c4bbdfSmrg .fs_vars = "uniform sampler2D atlas;\n", 14435c4bbdfSmrg }, 14535c4bbdfSmrg}; 14635c4bbdfSmrg 14735c4bbdfSmrgstatic char * 14835c4bbdfSmrgadd_var(char *cur, const char *add) 14935c4bbdfSmrg{ 15035c4bbdfSmrg char *new; 15135c4bbdfSmrg 15235c4bbdfSmrg if (!add) 15335c4bbdfSmrg return cur; 15435c4bbdfSmrg 15535c4bbdfSmrg new = realloc(cur, strlen(cur) + strlen(add) + 1); 15635c4bbdfSmrg if (!new) { 15735c4bbdfSmrg free(cur); 15835c4bbdfSmrg return NULL; 15935c4bbdfSmrg } 16035c4bbdfSmrg strcat(new, add); 16135c4bbdfSmrg return new; 16235c4bbdfSmrg} 16335c4bbdfSmrg 16435c4bbdfSmrgstatic char * 16535c4bbdfSmrgvs_location_vars(glamor_program_location locations) 16635c4bbdfSmrg{ 16735c4bbdfSmrg int l; 16835c4bbdfSmrg char *vars = strdup(""); 16935c4bbdfSmrg 17035c4bbdfSmrg for (l = 0; vars && l < ARRAY_SIZE(location_vars); l++) 17135c4bbdfSmrg if (locations & location_vars[l].location) 17235c4bbdfSmrg vars = add_var(vars, location_vars[l].vs_vars); 17335c4bbdfSmrg return vars; 17435c4bbdfSmrg} 17535c4bbdfSmrg 17635c4bbdfSmrgstatic char * 17735c4bbdfSmrgfs_location_vars(glamor_program_location locations) 17835c4bbdfSmrg{ 17935c4bbdfSmrg int l; 18035c4bbdfSmrg char *vars = strdup(""); 18135c4bbdfSmrg 18235c4bbdfSmrg for (l = 0; vars && l < ARRAY_SIZE(location_vars); l++) 18335c4bbdfSmrg if (locations & location_vars[l].location) 18435c4bbdfSmrg vars = add_var(vars, location_vars[l].fs_vars); 18535c4bbdfSmrg return vars; 18635c4bbdfSmrg} 18735c4bbdfSmrg 18835c4bbdfSmrgstatic const char vs_template[] = 18935c4bbdfSmrg "%s" /* version */ 190ed6184dfSmrg "%s" /* exts */ 19135c4bbdfSmrg "%s" /* defines */ 19235c4bbdfSmrg "%s" /* prim vs_vars */ 19335c4bbdfSmrg "%s" /* fill vs_vars */ 19435c4bbdfSmrg "%s" /* location vs_vars */ 19535c4bbdfSmrg GLAMOR_DECLARE_MATRIX 19635c4bbdfSmrg "void main() {\n" 19735c4bbdfSmrg "%s" /* prim vs_exec, outputs 'pos' and gl_Position */ 19835c4bbdfSmrg "%s" /* fill vs_exec */ 19935c4bbdfSmrg "}\n"; 20035c4bbdfSmrg 20135c4bbdfSmrgstatic const char fs_template[] = 20235c4bbdfSmrg "%s" /* version */ 203ed6184dfSmrg "%s" /* exts */ 20435c4bbdfSmrg GLAMOR_DEFAULT_PRECISION 20535c4bbdfSmrg "%s" /* defines */ 20635c4bbdfSmrg "%s" /* prim fs_vars */ 20735c4bbdfSmrg "%s" /* fill fs_vars */ 20835c4bbdfSmrg "%s" /* location fs_vars */ 20935c4bbdfSmrg "void main() {\n" 21035c4bbdfSmrg "%s" /* prim fs_exec */ 21135c4bbdfSmrg "%s" /* fill fs_exec */ 21235c4bbdfSmrg "%s" /* combine */ 21335c4bbdfSmrg "}\n"; 21435c4bbdfSmrg 21535c4bbdfSmrgstatic const char * 21635c4bbdfSmrgstr(const char *s) 21735c4bbdfSmrg{ 21835c4bbdfSmrg if (!s) 21935c4bbdfSmrg return ""; 22035c4bbdfSmrg return s; 22135c4bbdfSmrg} 22235c4bbdfSmrg 22335c4bbdfSmrgstatic const glamor_facet facet_null_fill = { 22435c4bbdfSmrg .name = "" 22535c4bbdfSmrg}; 22635c4bbdfSmrg 22735c4bbdfSmrg#define DBG 0 22835c4bbdfSmrg 22935c4bbdfSmrgstatic GLint 23035c4bbdfSmrgglamor_get_uniform(glamor_program *prog, 23135c4bbdfSmrg glamor_program_location location, 23235c4bbdfSmrg const char *name) 23335c4bbdfSmrg{ 23435c4bbdfSmrg GLint uniform; 23535c4bbdfSmrg if (location && (prog->locations & location) == 0) 23635c4bbdfSmrg return -2; 23735c4bbdfSmrg uniform = glGetUniformLocation(prog->prog, name); 23835c4bbdfSmrg#if DBG 23935c4bbdfSmrg ErrorF("%s uniform %d\n", name, uniform); 24035c4bbdfSmrg#endif 24135c4bbdfSmrg return uniform; 24235c4bbdfSmrg} 24335c4bbdfSmrg 24435c4bbdfSmrgBool 24535c4bbdfSmrgglamor_build_program(ScreenPtr screen, 24635c4bbdfSmrg glamor_program *prog, 24735c4bbdfSmrg const glamor_facet *prim, 24835c4bbdfSmrg const glamor_facet *fill, 24935c4bbdfSmrg const char *combine, 25035c4bbdfSmrg const char *defines) 25135c4bbdfSmrg{ 25235c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 25335c4bbdfSmrg 25435c4bbdfSmrg glamor_program_location locations = prim->locations; 25535c4bbdfSmrg glamor_program_flag flags = prim->flags; 25635c4bbdfSmrg 25735c4bbdfSmrg int version = prim->version; 25835c4bbdfSmrg char *version_string = NULL; 25935c4bbdfSmrg 26035c4bbdfSmrg char *fs_vars = NULL; 26135c4bbdfSmrg char *vs_vars = NULL; 26235c4bbdfSmrg 263ed6184dfSmrg char *vs_prog_string = NULL; 264ed6184dfSmrg char *fs_prog_string = NULL; 26535c4bbdfSmrg 26635c4bbdfSmrg GLint fs_prog, vs_prog; 267ed6184dfSmrg Bool gpu_shader4 = FALSE; 26835c4bbdfSmrg 26935c4bbdfSmrg if (!fill) 27035c4bbdfSmrg fill = &facet_null_fill; 27135c4bbdfSmrg 27235c4bbdfSmrg locations |= fill->locations; 27335c4bbdfSmrg flags |= fill->flags; 27435c4bbdfSmrg version = MAX(version, fill->version); 27535c4bbdfSmrg 276ed6184dfSmrg if (version > glamor_priv->glsl_version) { 277ed6184dfSmrg if (version == 130 && !glamor_priv->use_gpu_shader4) 278ed6184dfSmrg goto fail; 279ed6184dfSmrg else { 280ed6184dfSmrg version = 120; 281ed6184dfSmrg gpu_shader4 = TRUE; 282ed6184dfSmrg } 283ed6184dfSmrg } 28435c4bbdfSmrg 28535c4bbdfSmrg vs_vars = vs_location_vars(locations); 28635c4bbdfSmrg fs_vars = fs_location_vars(locations); 28735c4bbdfSmrg 28835c4bbdfSmrg if (!vs_vars) 28935c4bbdfSmrg goto fail; 29035c4bbdfSmrg if (!fs_vars) 29135c4bbdfSmrg goto fail; 29235c4bbdfSmrg 29335c4bbdfSmrg if (version) { 29435c4bbdfSmrg if (asprintf(&version_string, "#version %d\n", version) < 0) 29535c4bbdfSmrg version_string = NULL; 29635c4bbdfSmrg if (!version_string) 29735c4bbdfSmrg goto fail; 29835c4bbdfSmrg } 29935c4bbdfSmrg 30035c4bbdfSmrg if (asprintf(&vs_prog_string, 30135c4bbdfSmrg vs_template, 30235c4bbdfSmrg str(version_string), 303ed6184dfSmrg gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n" : "", 30435c4bbdfSmrg str(defines), 30535c4bbdfSmrg str(prim->vs_vars), 30635c4bbdfSmrg str(fill->vs_vars), 30735c4bbdfSmrg vs_vars, 30835c4bbdfSmrg str(prim->vs_exec), 30935c4bbdfSmrg str(fill->vs_exec)) < 0) 31035c4bbdfSmrg vs_prog_string = NULL; 31135c4bbdfSmrg 31235c4bbdfSmrg if (asprintf(&fs_prog_string, 31335c4bbdfSmrg fs_template, 31435c4bbdfSmrg str(version_string), 315ed6184dfSmrg gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n#define texelFetch texelFetch2D\n#define uint unsigned int\n" : "", 31635c4bbdfSmrg str(defines), 31735c4bbdfSmrg str(prim->fs_vars), 31835c4bbdfSmrg str(fill->fs_vars), 31935c4bbdfSmrg fs_vars, 32035c4bbdfSmrg str(prim->fs_exec), 32135c4bbdfSmrg str(fill->fs_exec), 32235c4bbdfSmrg str(combine)) < 0) 32335c4bbdfSmrg fs_prog_string = NULL; 32435c4bbdfSmrg 32535c4bbdfSmrg if (!vs_prog_string || !fs_prog_string) 32635c4bbdfSmrg goto fail; 32735c4bbdfSmrg 32835c4bbdfSmrg prog->prog = glCreateProgram(); 32935c4bbdfSmrg#if DBG 33035c4bbdfSmrg ErrorF("\n\tProgram %d for %s %s\n\tVertex shader:\n\n\t================\n%s\n\n\tFragment Shader:\n\n%s\t================\n", 33135c4bbdfSmrg prog->prog, prim->name, fill->name, vs_prog_string, fs_prog_string); 33235c4bbdfSmrg#endif 33335c4bbdfSmrg 33435c4bbdfSmrg prog->flags = flags; 33535c4bbdfSmrg prog->locations = locations; 33635c4bbdfSmrg prog->prim_use = prim->use; 33735c4bbdfSmrg prog->prim_use_render = prim->use_render; 33835c4bbdfSmrg prog->fill_use = fill->use; 33935c4bbdfSmrg prog->fill_use_render = fill->use_render; 34035c4bbdfSmrg 34135c4bbdfSmrg vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string); 34235c4bbdfSmrg fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string); 34335c4bbdfSmrg glAttachShader(prog->prog, vs_prog); 34435c4bbdfSmrg glDeleteShader(vs_prog); 34535c4bbdfSmrg glAttachShader(prog->prog, fs_prog); 34635c4bbdfSmrg glDeleteShader(fs_prog); 34735c4bbdfSmrg glBindAttribLocation(prog->prog, GLAMOR_VERTEX_POS, "primitive"); 34835c4bbdfSmrg 34935c4bbdfSmrg if (prim->source_name) { 35035c4bbdfSmrg#if DBG 35135c4bbdfSmrg ErrorF("Bind GLAMOR_VERTEX_SOURCE to %s\n", prim->source_name); 35235c4bbdfSmrg#endif 35335c4bbdfSmrg glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name); 35435c4bbdfSmrg } 35535c4bbdfSmrg if (prog->alpha == glamor_program_alpha_dual_blend) { 35635c4bbdfSmrg glBindFragDataLocationIndexed(prog->prog, 0, 0, "color0"); 35735c4bbdfSmrg glBindFragDataLocationIndexed(prog->prog, 0, 1, "color1"); 35835c4bbdfSmrg } 35935c4bbdfSmrg 36035c4bbdfSmrg glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name); 36135c4bbdfSmrg 36235c4bbdfSmrg prog->matrix_uniform = glamor_get_uniform(prog, glamor_program_location_none, "v_matrix"); 36335c4bbdfSmrg prog->fg_uniform = glamor_get_uniform(prog, glamor_program_location_fg, "fg"); 36435c4bbdfSmrg prog->bg_uniform = glamor_get_uniform(prog, glamor_program_location_bg, "bg"); 36535c4bbdfSmrg prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_offset"); 36635c4bbdfSmrg prog->fill_size_inv_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_size_inv"); 36735c4bbdfSmrg prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font"); 36835c4bbdfSmrg prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane"); 36935c4bbdfSmrg prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul"); 37035c4bbdfSmrg prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash"); 37135c4bbdfSmrg prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length"); 37235c4bbdfSmrg prog->atlas_uniform = glamor_get_uniform(prog, glamor_program_location_atlas, "atlas"); 37335c4bbdfSmrg 37435c4bbdfSmrg free(version_string); 375f2346221Smrg free(vs_prog_string); 376f2346221Smrg free(fs_prog_string); 37735c4bbdfSmrg free(fs_vars); 37835c4bbdfSmrg free(vs_vars); 37935c4bbdfSmrg return TRUE; 38035c4bbdfSmrgfail: 38135c4bbdfSmrg prog->failed = 1; 38235c4bbdfSmrg if (prog->prog) { 38335c4bbdfSmrg glDeleteProgram(prog->prog); 38435c4bbdfSmrg prog->prog = 0; 38535c4bbdfSmrg } 386ed6184dfSmrg free(vs_prog_string); 387ed6184dfSmrg free(fs_prog_string); 38835c4bbdfSmrg free(version_string); 38935c4bbdfSmrg free(fs_vars); 39035c4bbdfSmrg free(vs_vars); 39135c4bbdfSmrg return FALSE; 39235c4bbdfSmrg} 39335c4bbdfSmrg 39435c4bbdfSmrgBool 39535c4bbdfSmrgglamor_use_program(PixmapPtr pixmap, 39635c4bbdfSmrg GCPtr gc, 39735c4bbdfSmrg glamor_program *prog, 39835c4bbdfSmrg void *arg) 39935c4bbdfSmrg{ 40035c4bbdfSmrg glUseProgram(prog->prog); 40135c4bbdfSmrg 40235c4bbdfSmrg if (prog->prim_use && !prog->prim_use(pixmap, gc, prog, arg)) 40335c4bbdfSmrg return FALSE; 40435c4bbdfSmrg 40535c4bbdfSmrg if (prog->fill_use && !prog->fill_use(pixmap, gc, prog, arg)) 40635c4bbdfSmrg return FALSE; 40735c4bbdfSmrg 40835c4bbdfSmrg return TRUE; 40935c4bbdfSmrg} 41035c4bbdfSmrg 41135c4bbdfSmrgglamor_program * 41235c4bbdfSmrgglamor_use_program_fill(PixmapPtr pixmap, 41335c4bbdfSmrg GCPtr gc, 41435c4bbdfSmrg glamor_program_fill *program_fill, 41535c4bbdfSmrg const glamor_facet *prim) 41635c4bbdfSmrg{ 41735c4bbdfSmrg ScreenPtr screen = pixmap->drawable.pScreen; 41835c4bbdfSmrg glamor_program *prog = &program_fill->progs[gc->fillStyle]; 41935c4bbdfSmrg 42035c4bbdfSmrg int fill_style = gc->fillStyle; 42135c4bbdfSmrg const glamor_facet *fill; 42235c4bbdfSmrg 42335c4bbdfSmrg if (prog->failed) 42435c4bbdfSmrg return FALSE; 42535c4bbdfSmrg 42635c4bbdfSmrg if (!prog->prog) { 42735c4bbdfSmrg fill = glamor_facet_fill[fill_style]; 42835c4bbdfSmrg if (!fill) 42935c4bbdfSmrg return NULL; 43035c4bbdfSmrg 43135c4bbdfSmrg if (!glamor_build_program(screen, prog, prim, fill, NULL, NULL)) 43235c4bbdfSmrg return NULL; 43335c4bbdfSmrg } 43435c4bbdfSmrg 43535c4bbdfSmrg if (!glamor_use_program(pixmap, gc, prog, NULL)) 43635c4bbdfSmrg return NULL; 43735c4bbdfSmrg 43835c4bbdfSmrg return prog; 43935c4bbdfSmrg} 44035c4bbdfSmrg 44135c4bbdfSmrgstatic struct blendinfo composite_op_info[] = { 44235c4bbdfSmrg [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, 44335c4bbdfSmrg [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, 44435c4bbdfSmrg [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, 44535c4bbdfSmrg [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, 44635c4bbdfSmrg [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, 44735c4bbdfSmrg [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, 44835c4bbdfSmrg [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, 44935c4bbdfSmrg [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, 45035c4bbdfSmrg [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, 45135c4bbdfSmrg [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, 45235c4bbdfSmrg [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, 45335c4bbdfSmrg [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, 45435c4bbdfSmrg [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, 45535c4bbdfSmrg}; 45635c4bbdfSmrg 45735c4bbdfSmrgstatic void 45835c4bbdfSmrgglamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst) 45935c4bbdfSmrg{ 46035c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pDrawable->pScreen); 46135c4bbdfSmrg GLenum src_blend, dst_blend; 46235c4bbdfSmrg struct blendinfo *op_info; 46335c4bbdfSmrg 46435c4bbdfSmrg switch (alpha) { 46535c4bbdfSmrg case glamor_program_alpha_ca_first: 46635c4bbdfSmrg op = PictOpOutReverse; 46735c4bbdfSmrg break; 46835c4bbdfSmrg case glamor_program_alpha_ca_second: 46935c4bbdfSmrg op = PictOpAdd; 47035c4bbdfSmrg break; 47135c4bbdfSmrg default: 47235c4bbdfSmrg break; 47335c4bbdfSmrg } 47435c4bbdfSmrg 475ed6184dfSmrg if (!glamor_priv->is_gles) 47635c4bbdfSmrg glDisable(GL_COLOR_LOGIC_OP); 47735c4bbdfSmrg 47835c4bbdfSmrg if (op == PictOpSrc) 47935c4bbdfSmrg return; 48035c4bbdfSmrg 48135c4bbdfSmrg op_info = &composite_op_info[op]; 48235c4bbdfSmrg 48335c4bbdfSmrg src_blend = op_info->source_blend; 48435c4bbdfSmrg dst_blend = op_info->dest_blend; 48535c4bbdfSmrg 48635c4bbdfSmrg /* If there's no dst alpha channel, adjust the blend op so that we'll treat 48735c4bbdfSmrg * it as always 1. 48835c4bbdfSmrg */ 48935c4bbdfSmrg if (PICT_FORMAT_A(dst->format) == 0 && op_info->dest_alpha) { 49035c4bbdfSmrg if (src_blend == GL_DST_ALPHA) 49135c4bbdfSmrg src_blend = GL_ONE; 49235c4bbdfSmrg else if (src_blend == GL_ONE_MINUS_DST_ALPHA) 49335c4bbdfSmrg src_blend = GL_ZERO; 49435c4bbdfSmrg } 49535c4bbdfSmrg 49635c4bbdfSmrg /* Set up the source alpha value for blending in component alpha mode. */ 49735c4bbdfSmrg if (alpha == glamor_program_alpha_dual_blend) { 49835c4bbdfSmrg switch (dst_blend) { 49935c4bbdfSmrg case GL_SRC_ALPHA: 50035c4bbdfSmrg dst_blend = GL_SRC1_COLOR; 50135c4bbdfSmrg break; 50235c4bbdfSmrg case GL_ONE_MINUS_SRC_ALPHA: 50335c4bbdfSmrg dst_blend = GL_ONE_MINUS_SRC1_COLOR; 50435c4bbdfSmrg break; 50535c4bbdfSmrg } 50635c4bbdfSmrg } else if (alpha != glamor_program_alpha_normal) { 50735c4bbdfSmrg switch (dst_blend) { 50835c4bbdfSmrg case GL_SRC_ALPHA: 50935c4bbdfSmrg dst_blend = GL_SRC_COLOR; 51035c4bbdfSmrg break; 51135c4bbdfSmrg case GL_ONE_MINUS_SRC_ALPHA: 51235c4bbdfSmrg dst_blend = GL_ONE_MINUS_SRC_COLOR; 51335c4bbdfSmrg break; 51435c4bbdfSmrg } 51535c4bbdfSmrg } 51635c4bbdfSmrg 51735c4bbdfSmrg glEnable(GL_BLEND); 51835c4bbdfSmrg glBlendFunc(src_blend, dst_blend); 51935c4bbdfSmrg} 52035c4bbdfSmrg 52135c4bbdfSmrgstatic Bool 52235c4bbdfSmrguse_source_solid(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) 52335c4bbdfSmrg{ 5241b5d61b8Smrg PictSolidFill *solid = &src->pSourcePict->solidFill; 5251b5d61b8Smrg float color[4]; 52635c4bbdfSmrg 5271b5d61b8Smrg glamor_get_rgba_from_color(&solid->fullcolor, color); 52835c4bbdfSmrg glamor_set_blend(op, prog->alpha, dst); 5291b5d61b8Smrg glUniform4fv(prog->fg_uniform, 1, color); 53035c4bbdfSmrg 53135c4bbdfSmrg return TRUE; 53235c4bbdfSmrg} 53335c4bbdfSmrg 53435c4bbdfSmrgstatic const glamor_facet glamor_source_solid = { 53535c4bbdfSmrg .name = "render_solid", 53635c4bbdfSmrg .fs_exec = " vec4 source = fg;\n", 53735c4bbdfSmrg .locations = glamor_program_location_fg, 53835c4bbdfSmrg .use_render = use_source_solid, 53935c4bbdfSmrg}; 54035c4bbdfSmrg 54135c4bbdfSmrgstatic Bool 54235c4bbdfSmrguse_source_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) 54335c4bbdfSmrg{ 54435c4bbdfSmrg glamor_set_blend(op, prog->alpha, dst); 54535c4bbdfSmrg 54635c4bbdfSmrg return glamor_set_texture((PixmapPtr) src->pDrawable, 54735c4bbdfSmrg glamor_picture_red_is_alpha(dst), 54835c4bbdfSmrg 0, 0, 54935c4bbdfSmrg prog->fill_offset_uniform, 55035c4bbdfSmrg prog->fill_size_inv_uniform); 55135c4bbdfSmrg} 55235c4bbdfSmrg 55335c4bbdfSmrgstatic const glamor_facet glamor_source_picture = { 55435c4bbdfSmrg .name = "render_picture", 55535c4bbdfSmrg .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n", 55635c4bbdfSmrg .fs_exec = " vec4 source = texture2D(sampler, fill_pos);\n", 55735c4bbdfSmrg .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos, 55835c4bbdfSmrg .use_render = use_source_picture, 55935c4bbdfSmrg}; 56035c4bbdfSmrg 56135c4bbdfSmrgstatic Bool 56235c4bbdfSmrguse_source_1x1_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog) 56335c4bbdfSmrg{ 56435c4bbdfSmrg glamor_set_blend(op, prog->alpha, dst); 56535c4bbdfSmrg 56635c4bbdfSmrg return glamor_set_texture_pixmap((PixmapPtr) src->pDrawable, 56735c4bbdfSmrg glamor_picture_red_is_alpha(dst)); 56835c4bbdfSmrg} 56935c4bbdfSmrg 57035c4bbdfSmrgstatic const glamor_facet glamor_source_1x1_picture = { 57135c4bbdfSmrg .name = "render_picture", 57235c4bbdfSmrg .fs_exec = " vec4 source = texture2D(sampler, vec2(0.5));\n", 57335c4bbdfSmrg .locations = glamor_program_location_fillsamp, 57435c4bbdfSmrg .use_render = use_source_1x1_picture, 57535c4bbdfSmrg}; 57635c4bbdfSmrg 57735c4bbdfSmrgstatic const glamor_facet *glamor_facet_source[glamor_program_source_count] = { 57835c4bbdfSmrg [glamor_program_source_solid] = &glamor_source_solid, 57935c4bbdfSmrg [glamor_program_source_picture] = &glamor_source_picture, 58035c4bbdfSmrg [glamor_program_source_1x1_picture] = &glamor_source_1x1_picture, 58135c4bbdfSmrg}; 58235c4bbdfSmrg 58335c4bbdfSmrgstatic const char *glamor_combine[] = { 58435c4bbdfSmrg [glamor_program_alpha_normal] = " gl_FragColor = source * mask.a;\n", 58535c4bbdfSmrg [glamor_program_alpha_ca_first] = " gl_FragColor = source.a * mask;\n", 58635c4bbdfSmrg [glamor_program_alpha_ca_second] = " gl_FragColor = source * mask;\n", 58735c4bbdfSmrg [glamor_program_alpha_dual_blend] = " color0 = source * mask;\n" 58835c4bbdfSmrg " color1 = source.a * mask;\n" 58935c4bbdfSmrg}; 59035c4bbdfSmrg 59135c4bbdfSmrgstatic Bool 59235c4bbdfSmrgglamor_setup_one_program_render(ScreenPtr screen, 59335c4bbdfSmrg glamor_program *prog, 59435c4bbdfSmrg glamor_program_source source_type, 59535c4bbdfSmrg glamor_program_alpha alpha, 59635c4bbdfSmrg const glamor_facet *prim, 59735c4bbdfSmrg const char *defines) 59835c4bbdfSmrg{ 59935c4bbdfSmrg if (prog->failed) 60035c4bbdfSmrg return FALSE; 60135c4bbdfSmrg 60235c4bbdfSmrg if (!prog->prog) { 60335c4bbdfSmrg const glamor_facet *fill = glamor_facet_source[source_type]; 60435c4bbdfSmrg 60535c4bbdfSmrg if (!fill) 60635c4bbdfSmrg return FALSE; 60735c4bbdfSmrg 60835c4bbdfSmrg prog->alpha = alpha; 60935c4bbdfSmrg if (!glamor_build_program(screen, prog, prim, fill, glamor_combine[alpha], defines)) 61035c4bbdfSmrg return FALSE; 61135c4bbdfSmrg } 61235c4bbdfSmrg 61335c4bbdfSmrg return TRUE; 61435c4bbdfSmrg} 61535c4bbdfSmrg 61635c4bbdfSmrgglamor_program * 61735c4bbdfSmrgglamor_setup_program_render(CARD8 op, 61835c4bbdfSmrg PicturePtr src, 61935c4bbdfSmrg PicturePtr mask, 62035c4bbdfSmrg PicturePtr dst, 62135c4bbdfSmrg glamor_program_render *program_render, 62235c4bbdfSmrg const glamor_facet *prim, 62335c4bbdfSmrg const char *defines) 62435c4bbdfSmrg{ 62535c4bbdfSmrg ScreenPtr screen = dst->pDrawable->pScreen; 62635c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 62735c4bbdfSmrg glamor_program_alpha alpha; 62835c4bbdfSmrg glamor_program_source source_type; 62935c4bbdfSmrg glamor_program *prog; 63035c4bbdfSmrg 63135c4bbdfSmrg if (op > ARRAY_SIZE(composite_op_info)) 63235c4bbdfSmrg return NULL; 63335c4bbdfSmrg 63435c4bbdfSmrg if (glamor_is_component_alpha(mask)) { 63535c4bbdfSmrg if (glamor_priv->has_dual_blend) { 63635c4bbdfSmrg alpha = glamor_program_alpha_dual_blend; 63735c4bbdfSmrg } else { 63835c4bbdfSmrg /* This only works for PictOpOver */ 63935c4bbdfSmrg if (op != PictOpOver) 64035c4bbdfSmrg return NULL; 64135c4bbdfSmrg 64235c4bbdfSmrg alpha = glamor_program_alpha_ca_first; 64335c4bbdfSmrg } 64435c4bbdfSmrg } else 64535c4bbdfSmrg alpha = glamor_program_alpha_normal; 64635c4bbdfSmrg 64735c4bbdfSmrg if (src->pDrawable) { 64835c4bbdfSmrg 64935c4bbdfSmrg /* Can't do transforms, alphamaps or sourcing from non-pixmaps yet */ 65035c4bbdfSmrg if (src->transform || src->alphaMap || src->pDrawable->type != DRAWABLE_PIXMAP) 65135c4bbdfSmrg return NULL; 65235c4bbdfSmrg 65335c4bbdfSmrg if (src->pDrawable->width == 1 && src->pDrawable->height == 1 && src->repeat) 65435c4bbdfSmrg source_type = glamor_program_source_1x1_picture; 65535c4bbdfSmrg else 65635c4bbdfSmrg source_type = glamor_program_source_picture; 65735c4bbdfSmrg } else { 65835c4bbdfSmrg SourcePictPtr sp = src->pSourcePict; 65935c4bbdfSmrg if (!sp) 66035c4bbdfSmrg return NULL; 66135c4bbdfSmrg switch (sp->type) { 66235c4bbdfSmrg case SourcePictTypeSolidFill: 66335c4bbdfSmrg source_type = glamor_program_source_solid; 66435c4bbdfSmrg break; 66535c4bbdfSmrg default: 66635c4bbdfSmrg return NULL; 66735c4bbdfSmrg } 66835c4bbdfSmrg } 66935c4bbdfSmrg 67035c4bbdfSmrg prog = &program_render->progs[source_type][alpha]; 67135c4bbdfSmrg if (!glamor_setup_one_program_render(screen, prog, source_type, alpha, prim, defines)) 67235c4bbdfSmrg return NULL; 67335c4bbdfSmrg 67435c4bbdfSmrg if (alpha == glamor_program_alpha_ca_first) { 67535c4bbdfSmrg 67635c4bbdfSmrg /* Make sure we can also build the second program before 67735c4bbdfSmrg * deciding to use this path. 67835c4bbdfSmrg */ 67935c4bbdfSmrg if (!glamor_setup_one_program_render(screen, 68035c4bbdfSmrg &program_render->progs[source_type][glamor_program_alpha_ca_second], 68135c4bbdfSmrg source_type, glamor_program_alpha_ca_second, prim, 68235c4bbdfSmrg defines)) 68335c4bbdfSmrg return NULL; 68435c4bbdfSmrg } 68535c4bbdfSmrg return prog; 68635c4bbdfSmrg} 68735c4bbdfSmrg 68835c4bbdfSmrgBool 68935c4bbdfSmrgglamor_use_program_render(glamor_program *prog, 69035c4bbdfSmrg CARD8 op, 69135c4bbdfSmrg PicturePtr src, 69235c4bbdfSmrg PicturePtr dst) 69335c4bbdfSmrg{ 69435c4bbdfSmrg glUseProgram(prog->prog); 69535c4bbdfSmrg 69635c4bbdfSmrg if (prog->prim_use_render && !prog->prim_use_render(op, src, dst, prog)) 69735c4bbdfSmrg return FALSE; 69835c4bbdfSmrg 69935c4bbdfSmrg if (prog->fill_use_render && !prog->fill_use_render(op, src, dst, prog)) 70035c4bbdfSmrg return FALSE; 70135c4bbdfSmrg return TRUE; 70235c4bbdfSmrg} 703