xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

glamor_program.c (23411B)


      1 /*
      2  * Copyright © 2014 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 #include "glamor_priv.h"
     24 #include "glamor_transform.h"
     25 #include "glamor_program.h"
     26 
     27 static Bool
     28 use_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
     29 {
     30     return glamor_set_solid(pixmap, gc, TRUE, prog->fg_uniform);
     31 }
     32 
     33 const glamor_facet glamor_fill_solid = {
     34     .name = "solid",
     35     .fs_exec = "       gl_FragColor = fg;\n",
     36     .locations = glamor_program_location_fg,
     37     .use = use_solid,
     38 };
     39 
     40 static Bool
     41 use_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
     42 {
     43     return glamor_set_tiled(pixmap, gc, prog->fill_offset_uniform, prog->fill_size_inv_uniform);
     44 }
     45 
     46 static const glamor_facet glamor_fill_tile = {
     47     .name = "tile",
     48     .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n",
     49     .fs_exec =  "       gl_FragColor = texture2D(sampler, fill_pos);\n",
     50     .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos,
     51     .use = use_tile,
     52 };
     53 
     54 static Bool
     55 use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
     56 {
     57     return glamor_set_stippled(pixmap, gc, prog->fg_uniform,
     58                                prog->fill_offset_uniform,
     59                                prog->fill_size_inv_uniform);
     60 }
     61 
     62 static const glamor_facet glamor_fill_stipple = {
     63     .name = "stipple",
     64     .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n",
     65     .fs_exec = ("       float a = texture2D(sampler, fill_pos).w;\n"
     66                 "       if (a == 0.0)\n"
     67                 "               discard;\n"
     68                 "       gl_FragColor = fg;\n"),
     69     .locations = glamor_program_location_fg | glamor_program_location_fillsamp | glamor_program_location_fillpos,
     70     .use = use_stipple,
     71 };
     72 
     73 static Bool
     74 use_opaque_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
     75 {
     76     if (!use_stipple(pixmap, gc, prog, arg))
     77         return FALSE;
     78     glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
     79     return TRUE;
     80 }
     81 
     82 static const glamor_facet glamor_fill_opaque_stipple = {
     83     .name = "opaque_stipple",
     84     .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n",
     85     .fs_exec = ("       float a = texture2D(sampler, fill_pos).w;\n"
     86                 "       if (a == 0.0)\n"
     87                 "               gl_FragColor = bg;\n"
     88                 "       else\n"
     89                 "               gl_FragColor = fg;\n"),
     90     .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fillsamp | glamor_program_location_fillpos,
     91     .use = use_opaque_stipple
     92 };
     93 
     94 static const glamor_facet *glamor_facet_fill[4] = {
     95     &glamor_fill_solid,
     96     &glamor_fill_tile,
     97     &glamor_fill_stipple,
     98     &glamor_fill_opaque_stipple,
     99 };
    100 
    101 typedef struct {
    102     glamor_program_location     location;
    103     const char                  *vs_vars;
    104     const char                  *fs_vars;
    105 } glamor_location_var;
    106 
    107 static glamor_location_var location_vars[] = {
    108     {
    109         .location = glamor_program_location_fg,
    110         .fs_vars = "uniform vec4 fg;\n"
    111     },
    112     {
    113         .location = glamor_program_location_bg,
    114         .fs_vars = "uniform vec4 bg;\n"
    115     },
    116     {
    117         .location = glamor_program_location_fillsamp,
    118         .fs_vars = "uniform sampler2D sampler;\n"
    119     },
    120     {
    121         .location = glamor_program_location_fillpos,
    122         .vs_vars = ("uniform vec2 fill_offset;\n"
    123                     "uniform vec2 fill_size_inv;\n"
    124                     "varying vec2 fill_pos;\n"),
    125         .fs_vars = ("varying vec2 fill_pos;\n")
    126     },
    127     {
    128         .location = glamor_program_location_font,
    129         .fs_vars = "uniform usampler2D font;\n",
    130     },
    131     {
    132         .location = glamor_program_location_bitplane,
    133         .fs_vars = ("uniform uvec4 bitplane;\n"
    134                     "uniform vec4 bitmul;\n"),
    135     },
    136     {
    137         .location = glamor_program_location_dash,
    138         .vs_vars = "uniform float dash_length;\n",
    139         .fs_vars = "uniform sampler2D dash;\n",
    140     },
    141     {
    142         .location = glamor_program_location_atlas,
    143         .fs_vars = "uniform sampler2D atlas;\n",
    144     },
    145 };
    146 
    147 static char *
    148 add_var(char *cur, const char *add)
    149 {
    150     char *new;
    151 
    152     if (!add)
    153         return cur;
    154 
    155     new = realloc(cur, strlen(cur) + strlen(add) + 1);
    156     if (!new) {
    157         free(cur);
    158         return NULL;
    159     }
    160     strcat(new, add);
    161     return new;
    162 }
    163 
    164 static char *
    165 vs_location_vars(glamor_program_location locations)
    166 {
    167     int l;
    168     char *vars = strdup("");
    169 
    170     for (l = 0; vars && l < ARRAY_SIZE(location_vars); l++)
    171         if (locations & location_vars[l].location)
    172             vars = add_var(vars, location_vars[l].vs_vars);
    173     return vars;
    174 }
    175 
    176 static char *
    177 fs_location_vars(glamor_program_location locations)
    178 {
    179     int l;
    180     char *vars = strdup("");
    181 
    182     for (l = 0; vars && l < ARRAY_SIZE(location_vars); l++)
    183         if (locations & location_vars[l].location)
    184             vars = add_var(vars, location_vars[l].fs_vars);
    185     return vars;
    186 }
    187 
    188 static const char vs_template[] =
    189     "%s"                                /* version */
    190     "%s"                                /* exts */
    191     "%s"                                /* defines */
    192     "%s"                                /* prim vs_vars */
    193     "%s"                                /* fill vs_vars */
    194     "%s"                                /* location vs_vars */
    195     GLAMOR_DECLARE_MATRIX
    196     "void main() {\n"
    197     "%s"                                /* prim vs_exec, outputs 'pos' and gl_Position */
    198     "%s"                                /* fill vs_exec */
    199     "}\n";
    200 
    201 static const char fs_template[] =
    202     "%s"                                /* version */
    203     "%s"                                /* exts */
    204     GLAMOR_DEFAULT_PRECISION
    205     "%s"                                /* defines */
    206     "%s"                                /* prim fs_vars */
    207     "%s"                                /* fill fs_vars */
    208     "%s"                                /* location fs_vars */
    209     "void main() {\n"
    210     "%s"                                /* prim fs_exec */
    211     "%s"                                /* fill fs_exec */
    212     "%s"                                /* combine */
    213     "}\n";
    214 
    215 static const char *
    216 str(const char *s)
    217 {
    218     if (!s)
    219         return "";
    220     return s;
    221 }
    222 
    223 static const glamor_facet facet_null_fill = {
    224     .name = ""
    225 };
    226 
    227 #define DBG 0
    228 
    229 static GLint
    230 glamor_get_uniform(glamor_program               *prog,
    231                    glamor_program_location      location,
    232                    const char                   *name)
    233 {
    234     GLint uniform;
    235     if (location && (prog->locations & location) == 0)
    236         return -2;
    237     uniform = glGetUniformLocation(prog->prog, name);
    238 #if DBG
    239     ErrorF("%s uniform %d\n", name, uniform);
    240 #endif
    241     return uniform;
    242 }
    243 
    244 Bool
    245 glamor_build_program(ScreenPtr          screen,
    246                      glamor_program     *prog,
    247                      const glamor_facet *prim,
    248                      const glamor_facet *fill,
    249                      const char         *combine,
    250                      const char         *defines)
    251 {
    252     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    253 
    254     glamor_program_location     locations = prim->locations;
    255     glamor_program_flag         flags = prim->flags;
    256 
    257     int                         version = prim->version;
    258     char                        *version_string = NULL;
    259 
    260     char                        *fs_vars = NULL;
    261     char                        *vs_vars = NULL;
    262 
    263     char                        *vs_prog_string = NULL;
    264     char                        *fs_prog_string = NULL;
    265 
    266     GLint                       fs_prog, vs_prog;
    267     Bool                        gpu_shader4 = FALSE;
    268 
    269     if (!fill)
    270         fill = &facet_null_fill;
    271 
    272     locations |= fill->locations;
    273     flags |= fill->flags;
    274     version = MAX(version, fill->version);
    275 
    276     if (version > glamor_priv->glsl_version) {
    277         if (version == 130 && !glamor_priv->use_gpu_shader4)
    278             goto fail;
    279         else {
    280             version = 120;
    281             gpu_shader4 = TRUE;
    282         }
    283     }
    284 
    285     vs_vars = vs_location_vars(locations);
    286     fs_vars = fs_location_vars(locations);
    287 
    288     if (!vs_vars)
    289         goto fail;
    290     if (!fs_vars)
    291         goto fail;
    292 
    293     if (version) {
    294         if (asprintf(&version_string, "#version %d\n", version) < 0)
    295             version_string = NULL;
    296         if (!version_string)
    297             goto fail;
    298     }
    299 
    300     if (asprintf(&vs_prog_string,
    301                  vs_template,
    302                  str(version_string),
    303                  gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n" : "",
    304                  str(defines),
    305                  str(prim->vs_vars),
    306                  str(fill->vs_vars),
    307                  vs_vars,
    308                  str(prim->vs_exec),
    309                  str(fill->vs_exec)) < 0)
    310         vs_prog_string = NULL;
    311 
    312     if (asprintf(&fs_prog_string,
    313                  fs_template,
    314                  str(version_string),
    315                  gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n#define texelFetch texelFetch2D\n#define uint unsigned int\n" : "",
    316                  str(defines),
    317                  str(prim->fs_vars),
    318                  str(fill->fs_vars),
    319                  fs_vars,
    320                  str(prim->fs_exec),
    321                  str(fill->fs_exec),
    322                  str(combine)) < 0)
    323         fs_prog_string = NULL;
    324 
    325     if (!vs_prog_string || !fs_prog_string)
    326         goto fail;
    327 
    328     prog->prog = glCreateProgram();
    329 #if DBG
    330     ErrorF("\n\tProgram %d for %s %s\n\tVertex shader:\n\n\t================\n%s\n\n\tFragment Shader:\n\n%s\t================\n",
    331            prog->prog, prim->name, fill->name, vs_prog_string, fs_prog_string);
    332 #endif
    333 
    334     prog->flags = flags;
    335     prog->locations = locations;
    336     prog->prim_use = prim->use;
    337     prog->prim_use_render = prim->use_render;
    338     prog->fill_use = fill->use;
    339     prog->fill_use_render = fill->use_render;
    340 
    341     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string);
    342     fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string);
    343     free(vs_prog_string);
    344     free(fs_prog_string);
    345     glAttachShader(prog->prog, vs_prog);
    346     glDeleteShader(vs_prog);
    347     glAttachShader(prog->prog, fs_prog);
    348     glDeleteShader(fs_prog);
    349     glBindAttribLocation(prog->prog, GLAMOR_VERTEX_POS, "primitive");
    350 
    351     if (prim->source_name) {
    352 #if DBG
    353         ErrorF("Bind GLAMOR_VERTEX_SOURCE to %s\n", prim->source_name);
    354 #endif
    355         glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name);
    356     }
    357     if (prog->alpha == glamor_program_alpha_dual_blend) {
    358         glBindFragDataLocationIndexed(prog->prog, 0, 0, "color0");
    359         glBindFragDataLocationIndexed(prog->prog, 0, 1, "color1");
    360     }
    361 
    362     glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name);
    363 
    364     prog->matrix_uniform = glamor_get_uniform(prog, glamor_program_location_none, "v_matrix");
    365     prog->fg_uniform = glamor_get_uniform(prog, glamor_program_location_fg, "fg");
    366     prog->bg_uniform = glamor_get_uniform(prog, glamor_program_location_bg, "bg");
    367     prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_offset");
    368     prog->fill_size_inv_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_size_inv");
    369     prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
    370     prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane");
    371     prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul");
    372     prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash");
    373     prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length");
    374     prog->atlas_uniform = glamor_get_uniform(prog, glamor_program_location_atlas, "atlas");
    375 
    376     free(version_string);
    377     free(fs_vars);
    378     free(vs_vars);
    379     return TRUE;
    380 fail:
    381     prog->failed = 1;
    382     if (prog->prog) {
    383         glDeleteProgram(prog->prog);
    384         prog->prog = 0;
    385     }
    386     free(vs_prog_string);
    387     free(fs_prog_string);
    388     free(version_string);
    389     free(fs_vars);
    390     free(vs_vars);
    391     return FALSE;
    392 }
    393 
    394 Bool
    395 glamor_use_program(PixmapPtr            pixmap,
    396                    GCPtr                gc,
    397                    glamor_program       *prog,
    398                    void                 *arg)
    399 {
    400     glUseProgram(prog->prog);
    401 
    402     if (prog->prim_use && !prog->prim_use(pixmap, gc, prog, arg))
    403         return FALSE;
    404 
    405     if (prog->fill_use && !prog->fill_use(pixmap, gc, prog, arg))
    406         return FALSE;
    407 
    408     return TRUE;
    409 }
    410 
    411 glamor_program *
    412 glamor_use_program_fill(PixmapPtr               pixmap,
    413                         GCPtr                   gc,
    414                         glamor_program_fill     *program_fill,
    415                         const glamor_facet      *prim)
    416 {
    417     ScreenPtr                   screen = pixmap->drawable.pScreen;
    418     glamor_program              *prog = &program_fill->progs[gc->fillStyle];
    419 
    420     int                         fill_style = gc->fillStyle;
    421     const glamor_facet          *fill;
    422 
    423     if (prog->failed)
    424         return FALSE;
    425 
    426     if (!prog->prog) {
    427         fill = glamor_facet_fill[fill_style];
    428         if (!fill)
    429             return NULL;
    430 
    431         if (!glamor_build_program(screen, prog, prim, fill, NULL, NULL))
    432             return NULL;
    433     }
    434 
    435     if (!glamor_use_program(pixmap, gc, prog, NULL))
    436         return NULL;
    437 
    438     return prog;
    439 }
    440 
    441 static struct blendinfo composite_op_info[] = {
    442     [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO},
    443     [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO},
    444     [PictOpDst] = {0, 0, GL_ZERO, GL_ONE},
    445     [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
    446     [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE},
    447     [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO},
    448     [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA},
    449     [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO},
    450     [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA},
    451     [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
    452     [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA},
    453     [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
    454     [PictOpAdd] = {0, 0, GL_ONE, GL_ONE},
    455 };
    456 
    457 static void
    458 glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst)
    459 {
    460     glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pDrawable->pScreen);
    461     GLenum src_blend, dst_blend;
    462     struct blendinfo *op_info;
    463 
    464     switch (alpha) {
    465     case glamor_program_alpha_ca_first:
    466         op = PictOpOutReverse;
    467         break;
    468     case glamor_program_alpha_ca_second:
    469         op = PictOpAdd;
    470         break;
    471     default:
    472         break;
    473     }
    474 
    475     if (!glamor_priv->is_gles)
    476         glDisable(GL_COLOR_LOGIC_OP);
    477 
    478     if (op == PictOpSrc)
    479         return;
    480 
    481     op_info = &composite_op_info[op];
    482 
    483     src_blend = op_info->source_blend;
    484     dst_blend = op_info->dest_blend;
    485 
    486     /* If there's no dst alpha channel, adjust the blend op so that we'll treat
    487      * it as always 1.
    488      */
    489     if (PICT_FORMAT_A(dst->format) == 0 && op_info->dest_alpha) {
    490         if (src_blend == GL_DST_ALPHA)
    491             src_blend = GL_ONE;
    492         else if (src_blend == GL_ONE_MINUS_DST_ALPHA)
    493             src_blend = GL_ZERO;
    494     }
    495 
    496     /* Set up the source alpha value for blending in component alpha mode. */
    497     if (alpha == glamor_program_alpha_dual_blend) {
    498         switch (dst_blend) {
    499         case GL_SRC_ALPHA:
    500             dst_blend = GL_SRC1_COLOR;
    501             break;
    502         case GL_ONE_MINUS_SRC_ALPHA:
    503             dst_blend = GL_ONE_MINUS_SRC1_COLOR;
    504             break;
    505         }
    506     } else if (alpha != glamor_program_alpha_normal) {
    507         switch (dst_blend) {
    508         case GL_SRC_ALPHA:
    509             dst_blend = GL_SRC_COLOR;
    510             break;
    511         case GL_ONE_MINUS_SRC_ALPHA:
    512             dst_blend = GL_ONE_MINUS_SRC_COLOR;
    513             break;
    514         }
    515     }
    516 
    517     glEnable(GL_BLEND);
    518     glBlendFunc(src_blend, dst_blend);
    519 }
    520 
    521 static Bool
    522 use_source_solid(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog)
    523 {
    524     PictSolidFill *solid = &src->pSourcePict->solidFill;
    525     float color[4];
    526 
    527     glamor_get_rgba_from_color(&solid->fullcolor, color);
    528     glamor_set_blend(op, prog->alpha, dst);
    529     glUniform4fv(prog->fg_uniform, 1, color);
    530 
    531     return TRUE;
    532 }
    533 
    534 static const glamor_facet glamor_source_solid = {
    535     .name = "render_solid",
    536     .fs_exec = "       vec4 source = fg;\n",
    537     .locations = glamor_program_location_fg,
    538     .use_render = use_source_solid,
    539 };
    540 
    541 static Bool
    542 use_source_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog)
    543 {
    544     glamor_set_blend(op, prog->alpha, dst);
    545 
    546     return glamor_set_texture((PixmapPtr) src->pDrawable,
    547                               glamor_picture_red_is_alpha(dst),
    548                               0, 0,
    549                               prog->fill_offset_uniform,
    550                               prog->fill_size_inv_uniform);
    551 }
    552 
    553 static const glamor_facet glamor_source_picture = {
    554     .name = "render_picture",
    555     .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n",
    556     .fs_exec =  "       vec4 source = texture2D(sampler, fill_pos);\n",
    557     .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos,
    558     .use_render = use_source_picture,
    559 };
    560 
    561 static Bool
    562 use_source_1x1_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog)
    563 {
    564     glamor_set_blend(op, prog->alpha, dst);
    565 
    566     return glamor_set_texture_pixmap((PixmapPtr) src->pDrawable,
    567                                      glamor_picture_red_is_alpha(dst));
    568 }
    569 
    570 static const glamor_facet glamor_source_1x1_picture = {
    571     .name = "render_picture",
    572     .fs_exec =  "       vec4 source = texture2D(sampler, vec2(0.5));\n",
    573     .locations = glamor_program_location_fillsamp,
    574     .use_render = use_source_1x1_picture,
    575 };
    576 
    577 static const glamor_facet *glamor_facet_source[glamor_program_source_count] = {
    578     [glamor_program_source_solid] = &glamor_source_solid,
    579     [glamor_program_source_picture] = &glamor_source_picture,
    580     [glamor_program_source_1x1_picture] = &glamor_source_1x1_picture,
    581 };
    582 
    583 static const char *glamor_combine[] = {
    584     [glamor_program_alpha_normal]    = "       gl_FragColor = source * mask.a;\n",
    585     [glamor_program_alpha_ca_first]  = "       gl_FragColor = source.a * mask;\n",
    586     [glamor_program_alpha_ca_second] = "       gl_FragColor = source * mask;\n",
    587     [glamor_program_alpha_dual_blend] = "      color0 = source * mask;\n"
    588                                         "      color1 = source.a * mask;\n"
    589 };
    590 
    591 static Bool
    592 glamor_setup_one_program_render(ScreenPtr               screen,
    593                                 glamor_program          *prog,
    594                                 glamor_program_source   source_type,
    595                                 glamor_program_alpha    alpha,
    596                                 const glamor_facet      *prim,
    597                                 const char              *defines)
    598 {
    599     if (prog->failed)
    600         return FALSE;
    601 
    602     if (!prog->prog) {
    603         const glamor_facet      *fill = glamor_facet_source[source_type];
    604 
    605         if (!fill)
    606             return FALSE;
    607 
    608         prog->alpha = alpha;
    609         if (!glamor_build_program(screen, prog, prim, fill, glamor_combine[alpha], defines))
    610             return FALSE;
    611     }
    612 
    613     return TRUE;
    614 }
    615 
    616 glamor_program *
    617 glamor_setup_program_render(CARD8                 op,
    618                             PicturePtr            src,
    619                             PicturePtr            mask,
    620                             PicturePtr            dst,
    621                             glamor_program_render *program_render,
    622                             const glamor_facet    *prim,
    623                             const char            *defines)
    624 {
    625     ScreenPtr                   screen = dst->pDrawable->pScreen;
    626     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    627     glamor_program_alpha        alpha;
    628     glamor_program_source       source_type;
    629     glamor_program              *prog;
    630 
    631     if (op > ARRAY_SIZE(composite_op_info))
    632         return NULL;
    633 
    634     if (glamor_is_component_alpha(mask)) {
    635         if (glamor_priv->has_dual_blend) {
    636             alpha = glamor_program_alpha_dual_blend;
    637         } else {
    638             /* This only works for PictOpOver */
    639             if (op != PictOpOver)
    640                 return NULL;
    641 
    642             alpha = glamor_program_alpha_ca_first;
    643         }
    644     } else
    645         alpha = glamor_program_alpha_normal;
    646 
    647     if (src->pDrawable) {
    648 
    649         /* Can't do transforms, alphamaps or sourcing from non-pixmaps yet */
    650         if (src->transform || src->alphaMap || src->pDrawable->type != DRAWABLE_PIXMAP)
    651             return NULL;
    652 
    653         if (src->pDrawable->width == 1 && src->pDrawable->height == 1 && src->repeat)
    654             source_type = glamor_program_source_1x1_picture;
    655         else
    656             source_type = glamor_program_source_picture;
    657     } else {
    658         SourcePictPtr   sp = src->pSourcePict;
    659         if (!sp)
    660             return NULL;
    661         switch (sp->type) {
    662         case SourcePictTypeSolidFill:
    663             source_type = glamor_program_source_solid;
    664             break;
    665         default:
    666             return NULL;
    667         }
    668     }
    669 
    670     prog = &program_render->progs[source_type][alpha];
    671     if (!glamor_setup_one_program_render(screen, prog, source_type, alpha, prim, defines))
    672         return NULL;
    673 
    674     if (alpha == glamor_program_alpha_ca_first) {
    675 
    676 	  /* Make sure we can also build the second program before
    677 	   * deciding to use this path.
    678 	   */
    679 	  if (!glamor_setup_one_program_render(screen,
    680 					       &program_render->progs[source_type][glamor_program_alpha_ca_second],
    681 					       source_type, glamor_program_alpha_ca_second, prim,
    682 					       defines))
    683 	      return NULL;
    684     }
    685     return prog;
    686 }
    687 
    688 Bool
    689 glamor_use_program_render(glamor_program        *prog,
    690                           CARD8                 op,
    691                           PicturePtr            src,
    692                           PicturePtr            dst)
    693 {
    694     glUseProgram(prog->prog);
    695 
    696     if (prog->prim_use_render && !prog->prim_use_render(op, src, dst, prog))
    697         return FALSE;
    698 
    699     if (prog->fill_use_render && !prog->fill_use_render(op, src, dst, prog))
    700         return FALSE;
    701     return TRUE;
    702 }