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 27static Bool 28use_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) 29{ 30 return glamor_set_solid(pixmap, gc, TRUE, prog->fg_uniform); 31} 32 33const 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 40static Bool 41use_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 46static 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 54static Bool 55use_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 62static 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 73static Bool 74use_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 82static 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 94static 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 101typedef struct { 102 glamor_program_location location; 103 const char *vs_vars; 104 const char *fs_vars; 105} glamor_location_var; 106 107static 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 147static char * 148add_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 164static char * 165vs_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 176static char * 177fs_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 188static 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 201static 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 215static const char * 216str(const char *s) 217{ 218 if (!s) 219 return ""; 220 return s; 221} 222 223static const glamor_facet facet_null_fill = { 224 .name = "" 225}; 226 227#define DBG 0 228 229static GLint 230glamor_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 244Bool 245glamor_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 glAttachShader(prog->prog, vs_prog); 344 glDeleteShader(vs_prog); 345 glAttachShader(prog->prog, fs_prog); 346 glDeleteShader(fs_prog); 347 glBindAttribLocation(prog->prog, GLAMOR_VERTEX_POS, "primitive"); 348 349 if (prim->source_name) { 350#if DBG 351 ErrorF("Bind GLAMOR_VERTEX_SOURCE to %s\n", prim->source_name); 352#endif 353 glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name); 354 } 355 if (prog->alpha == glamor_program_alpha_dual_blend) { 356 glBindFragDataLocationIndexed(prog->prog, 0, 0, "color0"); 357 glBindFragDataLocationIndexed(prog->prog, 0, 1, "color1"); 358 } 359 360 glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name); 361 362 prog->matrix_uniform = glamor_get_uniform(prog, glamor_program_location_none, "v_matrix"); 363 prog->fg_uniform = glamor_get_uniform(prog, glamor_program_location_fg, "fg"); 364 prog->bg_uniform = glamor_get_uniform(prog, glamor_program_location_bg, "bg"); 365 prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_offset"); 366 prog->fill_size_inv_uniform = glamor_get_uniform(prog, glamor_program_location_fillpos, "fill_size_inv"); 367 prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font"); 368 prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane"); 369 prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul"); 370 prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash"); 371 prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length"); 372 prog->atlas_uniform = glamor_get_uniform(prog, glamor_program_location_atlas, "atlas"); 373 374 free(version_string); 375 free(vs_prog_string); 376 free(fs_prog_string); 377 free(fs_vars); 378 free(vs_vars); 379 return TRUE; 380fail: 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 394Bool 395glamor_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 411glamor_program * 412glamor_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 441static 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 457static void 458glamor_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 521static Bool 522use_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 534static 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 541static Bool 542use_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 553static 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 561static Bool 562use_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 570static 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 577static 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 583static 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 591static Bool 592glamor_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 616glamor_program * 617glamor_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 688Bool 689glamor_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} 703