xref: /OK3568_Linux_fs/external/xserver/glamor/glamor_program.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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
use_solid(PixmapPtr pixmap,GCPtr gc,glamor_program * prog,void * arg)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
use_tile(PixmapPtr pixmap,GCPtr gc,glamor_program * prog,void * arg)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
use_stipple(PixmapPtr pixmap,GCPtr gc,glamor_program * prog,void * arg)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
use_opaque_stipple(PixmapPtr pixmap,GCPtr gc,glamor_program * prog,void * arg)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 *
add_var(char * cur,const char * add)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 *
vs_location_vars(glamor_program_location locations)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 *
fs_location_vars(glamor_program_location locations)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"                                /* defines */
191     "%s"                                /* prim vs_vars */
192     "%s"                                /* fill vs_vars */
193     "%s"                                /* location vs_vars */
194     GLAMOR_DECLARE_MATRIX
195     "void main() {\n"
196     "%s"                                /* prim vs_exec, outputs 'pos' and gl_Position */
197     "%s"                                /* fill vs_exec */
198     "}\n";
199 
200 static const char fs_template[] =
201     "%s"                                /* version */
202     "%s"                                /* prim extensions */
203     "%s"                                /* fill extensions */
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 *
str(const char * s)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
glamor_get_uniform(glamor_program * prog,glamor_program_location location,const char * name)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
glamor_build_program(ScreenPtr screen,glamor_program * prog,const glamor_facet * prim,const glamor_facet * fill,const char * combine,const char * defines)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;
264     char                        *fs_prog_string;
265 
266     GLint                       fs_prog, vs_prog;
267 
268     if (!fill)
269         fill = &facet_null_fill;
270 
271     locations |= fill->locations;
272     flags |= fill->flags;
273     version = MAX(version, fill->version);
274 
275     if (version > glamor_priv->glsl_version)
276         goto fail;
277 
278     vs_vars = vs_location_vars(locations);
279     fs_vars = fs_location_vars(locations);
280 
281     if (!vs_vars)
282         goto fail;
283     if (!fs_vars)
284         goto fail;
285 
286     if (version && !glamor_priv->is_gles) {
287         if (asprintf(&version_string, "#version %d\n", version) < 0)
288             version_string = NULL;
289         if (!version_string)
290             goto fail;
291     }
292 
293     if (asprintf(&vs_prog_string,
294                  vs_template,
295                  str(version_string),
296                  str(defines),
297                  str(prim->vs_vars),
298                  str(fill->vs_vars),
299                  vs_vars,
300                  str(prim->vs_exec),
301                  str(fill->vs_exec)) < 0)
302         vs_prog_string = NULL;
303 
304     if (asprintf(&fs_prog_string,
305                  fs_template,
306                  str(version_string),
307                  str(prim->fs_extensions),
308                  str(fill->fs_extensions),
309                  str(defines),
310                  str(prim->fs_vars),
311                  str(fill->fs_vars),
312                  fs_vars,
313                  str(prim->fs_exec),
314                  str(fill->fs_exec),
315                  str(combine)) < 0)
316         fs_prog_string = NULL;
317 
318     if (!vs_prog_string || !fs_prog_string)
319         goto fail;
320 
321     prog->prog = glCreateProgram();
322 #if DBG
323     ErrorF("\n\tProgram %d for %s %s\n\tVertex shader:\n\n\t================\n%s\n\n\tFragment Shader:\n\n%s\t================\n",
324            prog->prog, prim->name, fill->name, vs_prog_string, fs_prog_string);
325 #endif
326 
327     prog->flags = flags;
328     prog->locations = locations;
329     prog->prim_use = prim->use;
330     prog->prim_use_render = prim->use_render;
331     prog->fill_use = fill->use;
332     prog->fill_use_render = fill->use_render;
333 
334     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string);
335     fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string);
336     free(vs_prog_string);
337     free(fs_prog_string);
338     glAttachShader(prog->prog, vs_prog);
339     glDeleteShader(vs_prog);
340     glAttachShader(prog->prog, fs_prog);
341     glDeleteShader(fs_prog);
342     glBindAttribLocation(prog->prog, GLAMOR_VERTEX_POS, "primitive");
343 
344     if (prim->source_name) {
345 #if DBG
346         ErrorF("Bind GLAMOR_VERTEX_SOURCE to %s\n", prim->source_name);
347 #endif
348         glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name);
349     }
350     if (prog->alpha == glamor_program_alpha_dual_blend) {
351         glBindFragDataLocationIndexed(prog->prog, 0, 0, "color0");
352         glBindFragDataLocationIndexed(prog->prog, 0, 1, "color1");
353     }
354 
355     glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name);
356 
357     prog->matrix_uniform = glamor_get_uniform(prog, glamor_program_location_none, "v_matrix");
358     prog->fg_uniform = glamor_get_uniform(prog, glamor_program_location_fg, "fg");
359     prog->bg_uniform = glamor_get_uniform(prog, glamor_program_location_bg, "bg");
360     prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_offset");
361     prog->fill_size_inv_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_size_inv");
362     prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
363     prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane");
364     prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul");
365     prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash");
366     prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length");
367     prog->atlas_uniform = glamor_get_uniform(prog, glamor_program_location_atlas, "atlas");
368 
369     free(version_string);
370     free(fs_vars);
371     free(vs_vars);
372     return TRUE;
373 fail:
374     prog->failed = 1;
375     if (prog->prog) {
376         glDeleteProgram(prog->prog);
377         prog->prog = 0;
378     }
379     free(version_string);
380     free(fs_vars);
381     free(vs_vars);
382     return FALSE;
383 }
384 
385 Bool
glamor_use_program(PixmapPtr pixmap,GCPtr gc,glamor_program * prog,void * arg)386 glamor_use_program(PixmapPtr            pixmap,
387                    GCPtr                gc,
388                    glamor_program       *prog,
389                    void                 *arg)
390 {
391     glUseProgram(prog->prog);
392 
393     if (prog->prim_use && !prog->prim_use(pixmap, gc, prog, arg))
394         return FALSE;
395 
396     if (prog->fill_use && !prog->fill_use(pixmap, gc, prog, arg))
397         return FALSE;
398 
399     return TRUE;
400 }
401 
402 glamor_program *
glamor_use_program_fill(PixmapPtr pixmap,GCPtr gc,glamor_program_fill * program_fill,const glamor_facet * prim)403 glamor_use_program_fill(PixmapPtr               pixmap,
404                         GCPtr                   gc,
405                         glamor_program_fill     *program_fill,
406                         const glamor_facet      *prim)
407 {
408     ScreenPtr                   screen = pixmap->drawable.pScreen;
409     glamor_program              *prog = &program_fill->progs[gc->fillStyle];
410 
411     int                         fill_style = gc->fillStyle;
412     const glamor_facet          *fill;
413 
414     if (prog->failed)
415         return FALSE;
416 
417     if (!prog->prog) {
418         fill = glamor_facet_fill[fill_style];
419         if (!fill)
420             return NULL;
421 
422         if (!glamor_build_program(screen, prog, prim, fill, NULL, NULL))
423             return NULL;
424     }
425 
426     if (!glamor_use_program(pixmap, gc, prog, NULL))
427         return NULL;
428 
429     return prog;
430 }
431 
432 static struct blendinfo composite_op_info[] = {
433     [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO},
434     [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO},
435     [PictOpDst] = {0, 0, GL_ZERO, GL_ONE},
436     [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
437     [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE},
438     [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO},
439     [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA},
440     [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO},
441     [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA},
442     [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
443     [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA},
444     [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
445     [PictOpAdd] = {0, 0, GL_ONE, GL_ONE},
446 };
447 
448 static void
glamor_set_blend(CARD8 op,glamor_program_alpha alpha,PicturePtr dst)449 glamor_set_blend(CARD8 op, glamor_program_alpha alpha, PicturePtr dst)
450 {
451     glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pDrawable->pScreen);
452     GLenum src_blend, dst_blend;
453     struct blendinfo *op_info;
454 
455     switch (alpha) {
456     case glamor_program_alpha_ca_first:
457         op = PictOpOutReverse;
458         break;
459     case glamor_program_alpha_ca_second:
460         op = PictOpAdd;
461         break;
462     default:
463         break;
464     }
465 
466     if (!glamor_priv->is_gles)
467         glDisable(GL_COLOR_LOGIC_OP);
468 
469     if (op == PictOpSrc)
470         return;
471 
472     op_info = &composite_op_info[op];
473 
474     src_blend = op_info->source_blend;
475     dst_blend = op_info->dest_blend;
476 
477     /* If there's no dst alpha channel, adjust the blend op so that we'll treat
478      * it as always 1.
479      */
480     if (PICT_FORMAT_A(dst->format) == 0 && op_info->dest_alpha) {
481         if (src_blend == GL_DST_ALPHA)
482             src_blend = GL_ONE;
483         else if (src_blend == GL_ONE_MINUS_DST_ALPHA)
484             src_blend = GL_ZERO;
485     }
486 
487     /* Set up the source alpha value for blending in component alpha mode. */
488     if (alpha == glamor_program_alpha_dual_blend) {
489         switch (dst_blend) {
490         case GL_SRC_ALPHA:
491             dst_blend = GL_SRC1_COLOR;
492             break;
493         case GL_ONE_MINUS_SRC_ALPHA:
494             dst_blend = GL_ONE_MINUS_SRC1_COLOR;
495             break;
496         }
497     } else if (alpha != glamor_program_alpha_normal) {
498         switch (dst_blend) {
499         case GL_SRC_ALPHA:
500             dst_blend = GL_SRC_COLOR;
501             break;
502         case GL_ONE_MINUS_SRC_ALPHA:
503             dst_blend = GL_ONE_MINUS_SRC_COLOR;
504             break;
505         }
506     }
507 
508     glEnable(GL_BLEND);
509     glBlendFunc(src_blend, dst_blend);
510 }
511 
512 static Bool
use_source_solid(CARD8 op,PicturePtr src,PicturePtr dst,glamor_program * prog)513 use_source_solid(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog)
514 {
515     PictSolidFill *solid = &src->pSourcePict->solidFill;
516     float color[4];
517 
518     glamor_get_rgba_from_color(&solid->fullcolor, color);
519     glamor_set_blend(op, prog->alpha, dst);
520     glUniform4fv(prog->fg_uniform, 1, color);
521 
522     return TRUE;
523 }
524 
525 static const glamor_facet glamor_source_solid = {
526     .name = "render_solid",
527     .fs_exec = "       vec4 source = fg;\n",
528     .locations = glamor_program_location_fg,
529     .use_render = use_source_solid,
530 };
531 
532 static Bool
use_source_picture(CARD8 op,PicturePtr src,PicturePtr dst,glamor_program * prog)533 use_source_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog)
534 {
535     glamor_set_blend(op, prog->alpha, dst);
536 
537     return glamor_set_texture((PixmapPtr) src->pDrawable,
538                               glamor_picture_red_is_alpha(dst),
539                               0, 0,
540                               prog->fill_offset_uniform,
541                               prog->fill_size_inv_uniform);
542 }
543 
544 static const glamor_facet glamor_source_picture = {
545     .name = "render_picture",
546     .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) * fill_size_inv;\n",
547     .fs_exec =  "       vec4 source = texture2D(sampler, fill_pos);\n",
548     .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos,
549     .use_render = use_source_picture,
550 };
551 
552 static Bool
use_source_1x1_picture(CARD8 op,PicturePtr src,PicturePtr dst,glamor_program * prog)553 use_source_1x1_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog)
554 {
555     glamor_set_blend(op, prog->alpha, dst);
556 
557     return glamor_set_texture_pixmap((PixmapPtr) src->pDrawable,
558                                      glamor_picture_red_is_alpha(dst));
559 }
560 
561 static const glamor_facet glamor_source_1x1_picture = {
562     .name = "render_picture",
563     .fs_exec =  "       vec4 source = texture2D(sampler, vec2(0.5));\n",
564     .locations = glamor_program_location_fillsamp,
565     .use_render = use_source_1x1_picture,
566 };
567 
568 static const glamor_facet *glamor_facet_source[glamor_program_source_count] = {
569     [glamor_program_source_solid] = &glamor_source_solid,
570     [glamor_program_source_picture] = &glamor_source_picture,
571     [glamor_program_source_1x1_picture] = &glamor_source_1x1_picture,
572 };
573 
574 static const char *glamor_combine[] = {
575     [glamor_program_alpha_normal]    = "       gl_FragColor = source * mask.a;\n",
576     [glamor_program_alpha_ca_first]  = "       gl_FragColor = source.a * mask;\n",
577     [glamor_program_alpha_ca_second] = "       gl_FragColor = source * mask;\n",
578     [glamor_program_alpha_dual_blend] = "      color0 = source * mask;\n"
579                                         "      color1 = source.a * mask;\n"
580 };
581 
582 static Bool
glamor_setup_one_program_render(ScreenPtr screen,glamor_program * prog,glamor_program_source source_type,glamor_program_alpha alpha,const glamor_facet * prim,const char * defines)583 glamor_setup_one_program_render(ScreenPtr               screen,
584                                 glamor_program          *prog,
585                                 glamor_program_source   source_type,
586                                 glamor_program_alpha    alpha,
587                                 const glamor_facet      *prim,
588                                 const char              *defines)
589 {
590     if (prog->failed)
591         return FALSE;
592 
593     if (!prog->prog) {
594         const glamor_facet      *fill = glamor_facet_source[source_type];
595 
596         if (!fill)
597             return FALSE;
598 
599         prog->alpha = alpha;
600         if (!glamor_build_program(screen, prog, prim, fill, glamor_combine[alpha], defines))
601             return FALSE;
602     }
603 
604     return TRUE;
605 }
606 
607 glamor_program *
glamor_setup_program_render(CARD8 op,PicturePtr src,PicturePtr mask,PicturePtr dst,glamor_program_render * program_render,const glamor_facet * prim,const char * defines)608 glamor_setup_program_render(CARD8                 op,
609                             PicturePtr            src,
610                             PicturePtr            mask,
611                             PicturePtr            dst,
612                             glamor_program_render *program_render,
613                             const glamor_facet    *prim,
614                             const char            *defines)
615 {
616     ScreenPtr                   screen = dst->pDrawable->pScreen;
617     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
618     glamor_program_alpha        alpha;
619     glamor_program_source       source_type;
620     glamor_program              *prog;
621 
622     if (op > ARRAY_SIZE(composite_op_info))
623         return NULL;
624 
625     if (glamor_is_component_alpha(mask)) {
626         if (glamor_priv->has_dual_blend) {
627             alpha = glamor_program_alpha_dual_blend;
628         } else {
629             /* This only works for PictOpOver */
630             if (op != PictOpOver)
631                 return NULL;
632 
633             alpha = glamor_program_alpha_ca_first;
634         }
635     } else
636         alpha = glamor_program_alpha_normal;
637 
638     if (src->pDrawable) {
639 
640         /* Can't do transforms, alphamaps or sourcing from non-pixmaps yet */
641         if (src->transform || src->alphaMap || src->pDrawable->type != DRAWABLE_PIXMAP)
642             return NULL;
643 
644         if (src->pDrawable->width == 1 && src->pDrawable->height == 1 && src->repeat)
645             source_type = glamor_program_source_1x1_picture;
646         else
647             source_type = glamor_program_source_picture;
648     } else {
649         SourcePictPtr   sp = src->pSourcePict;
650         if (!sp)
651             return NULL;
652         switch (sp->type) {
653         case SourcePictTypeSolidFill:
654             source_type = glamor_program_source_solid;
655             break;
656         default:
657             return NULL;
658         }
659     }
660 
661     prog = &program_render->progs[source_type][alpha];
662     if (!glamor_setup_one_program_render(screen, prog, source_type, alpha, prim, defines))
663         return NULL;
664 
665     if (alpha == glamor_program_alpha_ca_first) {
666 
667 	  /* Make sure we can also build the second program before
668 	   * deciding to use this path.
669 	   */
670 	  if (!glamor_setup_one_program_render(screen,
671 					       &program_render->progs[source_type][glamor_program_alpha_ca_second],
672 					       source_type, glamor_program_alpha_ca_second, prim,
673 					       defines))
674 	      return NULL;
675     }
676     return prog;
677 }
678 
679 Bool
glamor_use_program_render(glamor_program * prog,CARD8 op,PicturePtr src,PicturePtr dst)680 glamor_use_program_render(glamor_program        *prog,
681                           CARD8                 op,
682                           PicturePtr            src,
683                           PicturePtr            dst)
684 {
685     glUseProgram(prog->prog);
686 
687     if (prog->prim_use_render && !prog->prim_use_render(op, src, dst, prog))
688         return FALSE;
689 
690     if (prog->fill_use_render && !prog->fill_use_render(op, src, dst, prog))
691         return FALSE;
692     return TRUE;
693 }
694