1 /* 2 * Copyright 2009 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Eric Anholt <eric (at) anholt.net> 25 * Zhigang Gong <zhigang.gong (at) linux.intel.com> 26 * Junyan He <junyan.he (at) linux.intel.com> 27 * 28 */ 29 30 /** @file glamor_render.c 31 * 32 * Render acceleration implementation 33 */ 34 35 #include "glamor_priv.h" 36 37 #include "mipict.h" 38 #include "fbpict.h" 39 #if 0 40 //#define DEBUGF(str, ...) do {} while(0) 41 #define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) 42 //#define DEBUGRegionPrint(x) do {} while (0) 43 #define DEBUGRegionPrint RegionPrint 44 #endif 45 46 static struct blendinfo composite_op_info[] = { 47 [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, 48 [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, 49 [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, 50 [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, 51 [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, 52 [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, 53 [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, 54 [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, 55 [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, 56 [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, 57 [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, 58 [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, 59 [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, 60 }; 61 62 #define RepeatFix 10 63 static GLuint 64 glamor_create_composite_fs(glamor_screen_private *glamor_priv, struct shader_key *key, Bool enable_rel_sampler) 65 { 66 const char *repeat_define = 67 "#define RepeatNone 0\n" 68 "#define RepeatNormal 1\n" 69 "#define RepeatPad 2\n" 70 "#define RepeatReflect 3\n" 71 "#define RepeatFix 10\n" 72 "uniform int source_repeat_mode;\n" 73 "uniform int mask_repeat_mode;\n"; 74 const char *relocate_texture = 75 "vec2 rel_tex_coord(vec2 texture, vec4 wh, int repeat) \n" 76 "{\n" 77 " vec2 rel_tex; \n" 78 " rel_tex = texture * wh.xy; \n" 79 " if (repeat == RepeatFix + RepeatNone)\n" 80 " return rel_tex; \n" 81 " else if (repeat == RepeatFix + RepeatNormal) \n" 82 " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh.xy); \n" 83 " else if (repeat == RepeatFix + RepeatPad) { \n" 84 " if (rel_tex.x >= 1.0) \n" 85 " rel_tex.x = 1.0 - wh.z * wh.x / 2.; \n" 86 " else if (rel_tex.x < 0.0) \n" 87 " rel_tex.x = 0.0; \n" 88 " if (rel_tex.y >= 1.0) \n" 89 " rel_tex.y = 1.0 - wh.w * wh.y / 2.; \n" 90 " else if (rel_tex.y < 0.0) \n" 91 " rel_tex.y = 0.0; \n" 92 " rel_tex = rel_tex / wh.xy; \n" 93 " } else if (repeat == RepeatFix + RepeatReflect) {\n" 94 " if ((1.0 - mod(abs(floor(rel_tex.x)), 2.0)) < 0.001)\n" 95 " rel_tex.x = 2.0 - (1.0 - fract(rel_tex.x)) / wh.x;\n" 96 " else \n" 97 " rel_tex.x = fract(rel_tex.x) / wh.x;\n" 98 " if ((1.0 - mod(abs(floor(rel_tex.y)), 2.0)) < 0.001)\n" 99 " rel_tex.y = 2.0 - (1.0 - fract(rel_tex.y)) / wh.y;\n" 100 " else \n" 101 " rel_tex.y = fract(rel_tex.y) / wh.y;\n" 102 " } \n" 103 " return rel_tex; \n" 104 "}\n"; 105 /* The texture and the pixmap size is not match eaxctly, so can't sample it directly. 106 * rel_sampler will recalculate the texture coords.*/ 107 const char *rel_sampler = 108 " vec4 rel_sampler_rgba(sampler2D tex_image, vec2 tex, vec4 wh, int repeat)\n" 109 "{\n" 110 " if (repeat >= RepeatFix) {\n" 111 " tex = rel_tex_coord(tex, wh, repeat);\n" 112 " if (repeat == RepeatFix + RepeatNone) {\n" 113 " if (tex.x < 0.0 || tex.x >= 1.0 || \n" 114 " tex.y < 0.0 || tex.y >= 1.0)\n" 115 " return vec4(0.0, 0.0, 0.0, 0.0);\n" 116 " tex = (fract(tex) / wh.xy);\n" 117 " }\n" 118 " }\n" 119 " return texture(tex_image, tex);\n" 120 "}\n" 121 " vec4 rel_sampler_rgbx(sampler2D tex_image, vec2 tex, vec4 wh, int repeat)\n" 122 "{\n" 123 " if (repeat >= RepeatFix) {\n" 124 " tex = rel_tex_coord(tex, wh, repeat);\n" 125 " if (repeat == RepeatFix + RepeatNone) {\n" 126 " if (tex.x < 0.0 || tex.x >= 1.0 || \n" 127 " tex.y < 0.0 || tex.y >= 1.0)\n" 128 " return vec4(0.0, 0.0, 0.0, 0.0);\n" 129 " tex = (fract(tex) / wh.xy);\n" 130 " }\n" 131 " }\n" 132 " return vec4(texture(tex_image, tex).rgb, 1.0);\n" 133 "}\n"; 134 const char *stub_rel_sampler = 135 " vec4 rel_sampler_rgba(sampler2D tex_image, vec2 tex, vec4 wh, int repeat)\n" 136 "{\n" 137 " return texture(tex_image, tex);\n" 138 "}\n" 139 " vec4 rel_sampler_rgbx(sampler2D tex_image, vec2 tex, vec4 wh, int repeat)\n" 140 "{\n" 141 " return vec4(texture(tex_image, tex).rgb, 1.0);\n" 142 "}\n"; 143 144 const char *source_solid_fetch = 145 "uniform vec4 source;\n" 146 "vec4 get_source()\n" 147 "{\n" 148 " return source;\n" 149 "}\n"; 150 const char *source_alpha_pixmap_fetch = 151 "in vec2 source_texture;\n" 152 "uniform sampler2D source_sampler;\n" 153 "uniform vec4 source_wh;" 154 "vec4 get_source()\n" 155 "{\n" 156 " return rel_sampler_rgba(source_sampler, source_texture,\n" 157 " source_wh, source_repeat_mode);\n" 158 "}\n"; 159 const char *source_pixmap_fetch = 160 "in vec2 source_texture;\n" 161 "uniform sampler2D source_sampler;\n" 162 "uniform vec4 source_wh;\n" 163 "vec4 get_source()\n" 164 "{\n" 165 " return rel_sampler_rgbx(source_sampler, source_texture,\n" 166 " source_wh, source_repeat_mode);\n" 167 "}\n"; 168 const char *mask_none = 169 "vec4 get_mask()\n" 170 "{\n" 171 " return vec4(0.0, 0.0, 0.0, 1.0);\n" 172 "}\n"; 173 const char *mask_solid_fetch = 174 "uniform vec4 mask;\n" 175 "vec4 get_mask()\n" 176 "{\n" 177 " return mask;\n" 178 "}\n"; 179 const char *mask_alpha_pixmap_fetch = 180 "in vec2 mask_texture;\n" 181 "uniform sampler2D mask_sampler;\n" 182 "uniform vec4 mask_wh;\n" 183 "vec4 get_mask()\n" 184 "{\n" 185 " return rel_sampler_rgba(mask_sampler, mask_texture,\n" 186 " mask_wh, mask_repeat_mode);\n" 187 "}\n"; 188 const char *mask_pixmap_fetch = 189 "in vec2 mask_texture;\n" 190 "uniform sampler2D mask_sampler;\n" 191 "uniform vec4 mask_wh;\n" 192 "vec4 get_mask()\n" 193 "{\n" 194 " return rel_sampler_rgbx(mask_sampler, mask_texture,\n" 195 " mask_wh, mask_repeat_mode);\n" 196 "}\n"; 197 198 const char *dest_swizzle_default = 199 "vec4 dest_swizzle(vec4 color)\n" 200 "{" 201 " return color;" 202 "}"; 203 const char *dest_swizzle_alpha_to_red = 204 "vec4 dest_swizzle(vec4 color)\n" 205 "{" 206 " float undef;\n" 207 " return vec4(color.a, undef, undef, undef);" 208 "}"; 209 210 const char *in_normal = 211 "void main()\n" 212 "{\n" 213 " frag_color = dest_swizzle(get_source() * get_mask().a);\n" 214 "}\n"; 215 const char *in_ca_source = 216 "void main()\n" 217 "{\n" 218 " frag_color = dest_swizzle(get_source() * get_mask());\n" 219 "}\n"; 220 const char *in_ca_alpha = 221 "void main()\n" 222 "{\n" 223 " frag_color = dest_swizzle(get_source().a * get_mask());\n" 224 "}\n"; 225 const char *in_ca_dual_blend = 226 "out vec4 color0;\n" 227 "out vec4 color1;\n" 228 "void main()\n" 229 "{\n" 230 " color0 = dest_swizzle(get_source() * get_mask());\n" 231 " color1 = dest_swizzle(get_source().a * get_mask());\n" 232 "}\n"; 233 const char *in_ca_dual_blend_gles2 = 234 "void main()\n" 235 "{\n" 236 " gl_FragColor = dest_swizzle(get_source() * get_mask());\n" 237 " gl_SecondaryFragColorEXT = dest_swizzle(get_source().a * get_mask());\n" 238 "}\n"; 239 const char *header_ca_dual_blend_gles2 = 240 "#version 100\n" 241 "#extension GL_EXT_blend_func_extended : require\n" 242 GLAMOR_COMPAT_DEFINES_FS; 243 244 char *source; 245 const char *source_fetch; 246 const char *mask_fetch = ""; 247 const char *in; 248 const char *header; 249 const char *header_norm = glamor_priv->glsl_version > 120 ? 250 "#version 130\n" : 251 glamor_priv->use_gpu_shader4 ? 252 "#version 120\n#extension GL_EXT_gpu_shader4 : require\n" GLAMOR_COMPAT_DEFINES_FS : 253 "#version 120\n" GLAMOR_COMPAT_DEFINES_FS; 254 const char *header_es = glamor_priv->glsl_version > 100 ? "#version 300 es\n" : "#version 100\n" GLAMOR_COMPAT_DEFINES_FS; 255 const char *dest_swizzle; 256 GLuint prog; 257 258 switch (key->source) { 259 case SHADER_SOURCE_SOLID: 260 source_fetch = source_solid_fetch; 261 break; 262 case SHADER_SOURCE_TEXTURE_ALPHA: 263 source_fetch = source_alpha_pixmap_fetch; 264 break; 265 case SHADER_SOURCE_TEXTURE: 266 source_fetch = source_pixmap_fetch; 267 break; 268 default: 269 FatalError("Bad composite shader source"); 270 } 271 272 switch (key->mask) { 273 case SHADER_MASK_NONE: 274 mask_fetch = mask_none; 275 break; 276 case SHADER_MASK_SOLID: 277 mask_fetch = mask_solid_fetch; 278 break; 279 case SHADER_MASK_TEXTURE_ALPHA: 280 mask_fetch = mask_alpha_pixmap_fetch; 281 break; 282 case SHADER_MASK_TEXTURE: 283 mask_fetch = mask_pixmap_fetch; 284 break; 285 default: 286 FatalError("Bad composite shader mask"); 287 } 288 289 /* If we're storing to an a8 texture but our texture format is 290 * GL_RED because of a core context, then we need to make sure to 291 * put the alpha into the red channel. 292 */ 293 switch (key->dest_swizzle) { 294 case SHADER_DEST_SWIZZLE_DEFAULT: 295 dest_swizzle = dest_swizzle_default; 296 break; 297 case SHADER_DEST_SWIZZLE_ALPHA_TO_RED: 298 dest_swizzle = dest_swizzle_alpha_to_red; 299 break; 300 default: 301 FatalError("Bad composite shader dest swizzle"); 302 } 303 304 header = glamor_priv->is_gles ? header_es : header_norm; 305 switch (key->in) { 306 case glamor_program_alpha_normal: 307 in = in_normal; 308 break; 309 case glamor_program_alpha_ca_first: 310 in = in_ca_source; 311 break; 312 case glamor_program_alpha_ca_second: 313 in = in_ca_alpha; 314 break; 315 case glamor_program_alpha_dual_blend: 316 in = in_ca_dual_blend; 317 break; 318 case glamor_program_alpha_dual_blend_gles2: 319 in = in_ca_dual_blend_gles2; 320 header = header_ca_dual_blend_gles2; 321 break; 322 default: 323 FatalError("Bad composite IN type"); 324 } 325 326 XNFasprintf(&source, 327 "%s" 328 GLAMOR_DEFAULT_PRECISION 329 "%s%s%s%s%s%s%s%s", header, GLAMOR_COMPAT_DEFINES_FS, 330 repeat_define, relocate_texture, 331 enable_rel_sampler ? rel_sampler : stub_rel_sampler, 332 source_fetch, mask_fetch, dest_swizzle, in); 333 334 prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source); 335 free(source); 336 337 return prog; 338 } 339 340 static GLuint 341 glamor_create_composite_vs(glamor_screen_private* priv, struct shader_key *key) 342 { 343 const char *main_opening = 344 "in vec4 v_position;\n" 345 "in vec4 v_texcoord0;\n" 346 "in vec4 v_texcoord1;\n" 347 "out vec2 source_texture;\n" 348 "out vec2 mask_texture;\n" 349 "void main()\n" 350 "{\n" 351 " gl_Position = v_position;\n"; 352 const char *source_coords = " source_texture = v_texcoord0.xy;\n"; 353 const char *mask_coords = " mask_texture = v_texcoord1.xy;\n"; 354 const char *main_closing = "}\n"; 355 const char *source_coords_setup = ""; 356 const char *mask_coords_setup = ""; 357 const char *version_gles2 = "#version 100\n"; 358 const char *version_gles3 = "#version 300 es\n"; 359 const char *version = priv->glsl_version > 120 ? "#version 130\n" : "#version 120\n"; 360 const char *defines = priv->glsl_version > 120 ? "": GLAMOR_COMPAT_DEFINES_VS; 361 char *source; 362 GLuint prog; 363 364 if (key->source != SHADER_SOURCE_SOLID) 365 source_coords_setup = source_coords; 366 367 if (key->mask != SHADER_MASK_NONE && key->mask != SHADER_MASK_SOLID) 368 mask_coords_setup = mask_coords; 369 370 if (priv->is_gles) 371 version = version_gles2; 372 373 if (priv->is_gles && priv->glsl_version > 120) 374 version = version_gles3; 375 376 XNFasprintf(&source, 377 "%s" 378 GLAMOR_DEFAULT_PRECISION 379 "%s%s%s%s%s", 380 version, defines, main_opening, source_coords_setup, 381 mask_coords_setup, main_closing); 382 383 prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, source); 384 free(source); 385 386 return prog; 387 } 388 389 static void 390 glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, 391 glamor_composite_shader *shader) 392 { 393 GLuint vs, fs, prog; 394 GLint source_sampler_uniform_location, mask_sampler_uniform_location; 395 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 396 Bool enable_rel_sampler = TRUE; 397 398 glamor_make_current(glamor_priv); 399 vs = glamor_create_composite_vs(glamor_priv, key); 400 if (vs == 0) 401 return; 402 fs = glamor_create_composite_fs(glamor_priv, key, enable_rel_sampler); 403 if (fs == 0) 404 return; 405 406 prog = glCreateProgram(); 407 glAttachShader(prog, vs); 408 glAttachShader(prog, fs); 409 glDeleteShader(vs); 410 glDeleteShader(fs); 411 412 glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position"); 413 glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); 414 glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1"); 415 416 if (key->in == glamor_program_alpha_dual_blend) { 417 glBindFragDataLocationIndexed(prog, 0, 0, "color0"); 418 glBindFragDataLocationIndexed(prog, 0, 1, "color1"); 419 } 420 421 if (!glamor_link_glsl_prog(screen, prog, "composite")) { 422 /* Failed to link the shader, try again without rel_sampler. */ 423 enable_rel_sampler = FALSE; 424 glDetachShader(prog, fs); 425 fs = glamor_create_composite_fs(glamor_priv, key, enable_rel_sampler); 426 if (fs == 0) 427 return; 428 glAttachShader(prog, fs); 429 glDeleteShader(fs); 430 431 if (!glamor_link_glsl_prog(screen, prog, "composite")) { 432 glDeleteProgram(prog); 433 return; 434 } 435 } 436 437 shader->prog = prog; 438 439 glUseProgram(prog); 440 441 if (key->source == SHADER_SOURCE_SOLID) { 442 shader->source_uniform_location = glGetUniformLocation(prog, "source"); 443 } 444 else { 445 source_sampler_uniform_location = 446 glGetUniformLocation(prog, "source_sampler"); 447 glUniform1i(source_sampler_uniform_location, 0); 448 shader->source_wh = glGetUniformLocation(prog, "source_wh"); 449 shader->source_repeat_mode = 450 glGetUniformLocation(prog, "source_repeat_mode"); 451 } 452 453 if (key->mask != SHADER_MASK_NONE) { 454 if (key->mask == SHADER_MASK_SOLID) { 455 shader->mask_uniform_location = glGetUniformLocation(prog, "mask"); 456 } 457 else { 458 mask_sampler_uniform_location = 459 glGetUniformLocation(prog, "mask_sampler"); 460 glUniform1i(mask_sampler_uniform_location, 1); 461 shader->mask_wh = glGetUniformLocation(prog, "mask_wh"); 462 shader->mask_repeat_mode = 463 glGetUniformLocation(prog, "mask_repeat_mode"); 464 } 465 } 466 } 467 468 static glamor_composite_shader * 469 glamor_lookup_composite_shader(ScreenPtr screen, struct 470 shader_key 471 *key) 472 { 473 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 474 glamor_composite_shader *shader; 475 476 shader = &glamor_priv->composite_shader[key->source][key->mask][key->in][key->dest_swizzle]; 477 if (shader->prog == 0) 478 glamor_create_composite_shader(screen, key, shader); 479 480 return shader; 481 } 482 483 static GLenum 484 glamor_translate_blend_alpha_to_red(GLenum blend) 485 { 486 switch (blend) { 487 case GL_SRC_ALPHA: 488 return GL_SRC_COLOR; 489 case GL_DST_ALPHA: 490 return GL_DST_COLOR; 491 case GL_ONE_MINUS_SRC_ALPHA: 492 return GL_ONE_MINUS_SRC_COLOR; 493 case GL_ONE_MINUS_DST_ALPHA: 494 return GL_ONE_MINUS_DST_COLOR; 495 default: 496 return blend; 497 } 498 } 499 500 static Bool 501 glamor_set_composite_op(ScreenPtr screen, 502 CARD8 op, struct blendinfo *op_info_result, 503 PicturePtr dest, PicturePtr mask, 504 enum ca_state ca_state, 505 struct shader_key *key) 506 { 507 GLenum source_blend, dest_blend; 508 struct blendinfo *op_info; 509 510 if (op >= ARRAY_SIZE(composite_op_info)) { 511 glamor_fallback("unsupported render op %d \n", op); 512 return GL_FALSE; 513 } 514 515 op_info = &composite_op_info[op]; 516 517 source_blend = op_info->source_blend; 518 dest_blend = op_info->dest_blend; 519 520 /* If there's no dst alpha channel, adjust the blend op so that we'll treat 521 * it as always 1. 522 */ 523 if (PICT_FORMAT_A(dest->format) == 0 && op_info->dest_alpha) { 524 if (source_blend == GL_DST_ALPHA) 525 source_blend = GL_ONE; 526 else if (source_blend == GL_ONE_MINUS_DST_ALPHA) 527 source_blend = GL_ZERO; 528 } 529 530 /* Set up the source alpha value for blending in component alpha mode. */ 531 if (ca_state == CA_DUAL_BLEND) { 532 switch (dest_blend) { 533 case GL_SRC_ALPHA: 534 dest_blend = GL_SRC1_COLOR; 535 break; 536 case GL_ONE_MINUS_SRC_ALPHA: 537 dest_blend = GL_ONE_MINUS_SRC1_COLOR; 538 break; 539 } 540 } else if (mask && mask->componentAlpha 541 && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) { 542 switch (dest_blend) { 543 case GL_SRC_ALPHA: 544 dest_blend = GL_SRC_COLOR; 545 break; 546 case GL_ONE_MINUS_SRC_ALPHA: 547 dest_blend = GL_ONE_MINUS_SRC_COLOR; 548 break; 549 } 550 } 551 552 /* If we're outputting our alpha to the red channel, then any 553 * reads of alpha for blending need to come from the red channel. 554 */ 555 if (key->dest_swizzle == SHADER_DEST_SWIZZLE_ALPHA_TO_RED) { 556 source_blend = glamor_translate_blend_alpha_to_red(source_blend); 557 dest_blend = glamor_translate_blend_alpha_to_red(dest_blend); 558 } 559 560 op_info_result->source_blend = source_blend; 561 op_info_result->dest_blend = dest_blend; 562 op_info_result->source_alpha = op_info->source_alpha; 563 op_info_result->dest_alpha = op_info->dest_alpha; 564 565 return TRUE; 566 } 567 568 static void 569 glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, 570 PicturePtr picture, 571 PixmapPtr pixmap, 572 GLuint wh_location, GLuint repeat_location, 573 glamor_pixmap_private *dest_priv) 574 { 575 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 576 glamor_pixmap_fbo *fbo = pixmap_priv->fbo; 577 float wh[4]; 578 int repeat_type; 579 580 glamor_make_current(glamor_priv); 581 582 /* The red channel swizzling doesn't depend on whether we're using 583 * 'fbo' as source or mask as we must have the same answer in case 584 * the same fbo is being used for both. That means the mask 585 * channel will sometimes get red bits in the R channel, and 586 * sometimes get zero bits in the R channel, which is harmless. 587 */ 588 glamor_bind_texture(glamor_priv, GL_TEXTURE0 + unit, fbo, 589 dest_priv->fbo->is_red); 590 repeat_type = picture->repeatType; 591 switch (picture->repeatType) { 592 case RepeatNone: 593 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 594 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 595 break; 596 case RepeatNormal: 597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 599 break; 600 case RepeatPad: 601 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 602 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 603 break; 604 case RepeatReflect: 605 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 606 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 607 break; 608 } 609 610 switch (picture->filter) { 611 default: 612 case PictFilterFast: 613 case PictFilterNearest: 614 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 615 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 616 break; 617 case PictFilterGood: 618 case PictFilterBest: 619 case PictFilterBilinear: 620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 621 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 622 break; 623 } 624 625 /* Handle RepeatNone in the shader when the source is missing the 626 * alpha channel, as GL will return an alpha for 1 if the texture 627 * is RGB (no alpha), which we use for 16bpp textures. 628 */ 629 if (glamor_pixmap_priv_is_large(pixmap_priv) || 630 (!PICT_FORMAT_A(picture->format) && 631 repeat_type == RepeatNone && picture->transform)) { 632 glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap, pixmap_priv); 633 glUniform4fv(wh_location, 1, wh); 634 635 repeat_type += RepeatFix; 636 } 637 638 glUniform1i(repeat_location, repeat_type); 639 } 640 641 static void 642 glamor_set_composite_solid(float *color, GLint uniform_location) 643 { 644 glUniform4fv(uniform_location, 1, color); 645 } 646 647 static char 648 glamor_get_picture_location(PicturePtr picture) 649 { 650 if (picture == NULL) 651 return ' '; 652 653 if (picture->pDrawable == NULL) { 654 switch (picture->pSourcePict->type) { 655 case SourcePictTypeSolidFill: 656 return 'c'; 657 case SourcePictTypeLinear: 658 return 'l'; 659 case SourcePictTypeRadial: 660 return 'r'; 661 default: 662 return '?'; 663 } 664 } 665 return glamor_get_drawable_location(picture->pDrawable); 666 } 667 668 static void * 669 glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) 670 { 671 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 672 int vert_size; 673 char *vbo_offset; 674 float *vb; 675 676 glamor_priv->render_nr_quads = 0; 677 glamor_priv->vb_stride = 2 * sizeof(float); 678 if (glamor_priv->has_source_coords) 679 glamor_priv->vb_stride += 2 * sizeof(float); 680 if (glamor_priv->has_mask_coords) 681 glamor_priv->vb_stride += 2 * sizeof(float); 682 683 vert_size = n_verts * glamor_priv->vb_stride; 684 685 glamor_make_current(glamor_priv); 686 vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset); 687 688 glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 689 glamor_priv->vb_stride, vbo_offset); 690 glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 691 692 if (glamor_priv->has_source_coords) { 693 glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, 694 GL_FLOAT, GL_FALSE, 695 glamor_priv->vb_stride, 696 vbo_offset + 2 * sizeof(float)); 697 glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); 698 } 699 700 if (glamor_priv->has_mask_coords) { 701 glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE, 702 glamor_priv->vb_stride, 703 vbo_offset + (glamor_priv->has_source_coords ? 704 4 : 2) * sizeof(float)); 705 glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); 706 } 707 708 return vb; 709 } 710 711 static void 712 glamor_flush_composite_rects(ScreenPtr screen) 713 { 714 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 715 716 glamor_make_current(glamor_priv); 717 718 if (!glamor_priv->render_nr_quads) 719 return; 720 721 glamor_glDrawArrays_GL_QUADS(glamor_priv, glamor_priv->render_nr_quads); 722 } 723 724 static const int pict_format_combine_tab[][3] = { 725 {PICT_TYPE_ARGB, PICT_TYPE_A, PICT_TYPE_ARGB}, 726 {PICT_TYPE_ABGR, PICT_TYPE_A, PICT_TYPE_ABGR}, 727 }; 728 729 static Bool 730 combine_pict_format(PictFormatShort * des, const PictFormatShort src, 731 const PictFormatShort mask, glamor_program_alpha in_ca) 732 { 733 PictFormatShort new_vis; 734 int src_type, mask_type, src_bpp; 735 int i; 736 737 if (src == mask) { 738 *des = src; 739 return TRUE; 740 } 741 src_bpp = PICT_FORMAT_BPP(src); 742 743 assert(src_bpp == PICT_FORMAT_BPP(mask)); 744 745 new_vis = PICT_FORMAT_VIS(src) | PICT_FORMAT_VIS(mask); 746 747 switch (in_ca) { 748 case glamor_program_alpha_normal: 749 src_type = PICT_FORMAT_TYPE(src); 750 mask_type = PICT_TYPE_A; 751 break; 752 case glamor_program_alpha_ca_first: 753 src_type = PICT_FORMAT_TYPE(src); 754 mask_type = PICT_FORMAT_TYPE(mask); 755 break; 756 case glamor_program_alpha_ca_second: 757 src_type = PICT_TYPE_A; 758 mask_type = PICT_FORMAT_TYPE(mask); 759 break; 760 case glamor_program_alpha_dual_blend: 761 case glamor_program_alpha_dual_blend_gles2: 762 src_type = PICT_FORMAT_TYPE(src); 763 mask_type = PICT_FORMAT_TYPE(mask); 764 break; 765 default: 766 return FALSE; 767 } 768 769 if (src_type == mask_type) { 770 *des = PICT_VISFORMAT(src_bpp, src_type, new_vis); 771 return TRUE; 772 } 773 774 for (i = 0; i < ARRAY_SIZE(pict_format_combine_tab); i++) { 775 if ((src_type == pict_format_combine_tab[i][0] 776 && mask_type == pict_format_combine_tab[i][1]) 777 || (src_type == pict_format_combine_tab[i][1] 778 && mask_type == pict_format_combine_tab[i][0])) { 779 *des = PICT_VISFORMAT(src_bpp, pict_format_combine_tab[i] 780 [2], new_vis); 781 return TRUE; 782 } 783 } 784 return FALSE; 785 } 786 787 static void 788 glamor_set_normalize_tcoords_generic(PixmapPtr pixmap, 789 glamor_pixmap_private *priv, 790 int repeat_type, 791 float *matrix, 792 float xscale, float yscale, 793 int x1, int y1, int x2, int y2, 794 float *texcoords, 795 int stride) 796 { 797 if (!matrix && repeat_type == RepeatNone) 798 glamor_set_normalize_tcoords_ext(priv, xscale, yscale, 799 x1, y1, 800 x2, y2, texcoords, stride); 801 else if (matrix && repeat_type == RepeatNone) 802 glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, 803 yscale, x1, y1, 804 x2, y2, 805 texcoords, stride); 806 else if (!matrix && repeat_type != RepeatNone) 807 glamor_set_repeat_normalize_tcoords_ext(pixmap, priv, repeat_type, 808 xscale, yscale, 809 x1, y1, 810 x2, y2, 811 texcoords, stride); 812 else if (matrix && repeat_type != RepeatNone) 813 glamor_set_repeat_transformed_normalize_tcoords_ext(pixmap, priv, repeat_type, 814 matrix, xscale, 815 yscale, x1, y1, x2, 816 y2, 817 texcoords, stride); 818 } 819 820 /** 821 * Returns whether the general composite path supports this picture 822 * format for a pixmap that is permanently stored in an FBO (as 823 * opposed to the dynamic upload path). 824 * 825 * We could support many more formats by using GL_ARB_texture_view to 826 * parse the same bits as different formats. For now, we only support 827 * tweaking whether we sample the alpha bits, or just force them to 1. 828 */ 829 static Bool 830 glamor_render_format_is_supported(PicturePtr picture) 831 { 832 PictFormatShort storage_format; 833 glamor_screen_private *glamor_priv; 834 struct glamor_format *f; 835 836 /* Source-only pictures should always work */ 837 if (!picture->pDrawable) 838 return TRUE; 839 840 glamor_priv = glamor_get_screen_private(picture->pDrawable->pScreen); 841 f = &glamor_priv->formats[picture->pDrawable->depth]; 842 843 if (!f->rendering_supported) 844 return FALSE; 845 846 storage_format = f->render_format; 847 848 switch (picture->format) { 849 case PICT_a2r10g10b10: 850 return storage_format == PICT_x2r10g10b10; 851 case PICT_a8r8g8b8: 852 case PICT_x8r8g8b8: 853 return storage_format == PICT_a8r8g8b8 || storage_format == PICT_x8r8g8b8; 854 case PICT_a1r5g5b5: 855 return storage_format == PICT_x1r5g5b5; 856 default: 857 return picture->format == storage_format; 858 } 859 } 860 861 static Bool 862 glamor_composite_choose_shader(CARD8 op, 863 PicturePtr source, 864 PicturePtr mask, 865 PicturePtr dest, 866 PixmapPtr source_pixmap, 867 PixmapPtr mask_pixmap, 868 PixmapPtr dest_pixmap, 869 glamor_pixmap_private *source_pixmap_priv, 870 glamor_pixmap_private *mask_pixmap_priv, 871 glamor_pixmap_private *dest_pixmap_priv, 872 struct shader_key *s_key, 873 glamor_composite_shader ** shader, 874 struct blendinfo *op_info, 875 PictFormatShort *psaved_source_format, 876 enum ca_state ca_state) 877 { 878 ScreenPtr screen = dest->pDrawable->pScreen; 879 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 880 Bool source_needs_upload = FALSE; 881 Bool mask_needs_upload = FALSE; 882 PictFormatShort saved_source_format = 0; 883 struct shader_key key; 884 GLfloat source_solid_color[4]; 885 GLfloat mask_solid_color[4]; 886 Bool ret = FALSE; 887 888 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { 889 glamor_fallback("dest has no fbo.\n"); 890 goto fail; 891 } 892 893 if (!glamor_render_format_is_supported(dest)) { 894 glamor_fallback("Unsupported dest picture format.\n"); 895 goto fail; 896 } 897 898 memset(&key, 0, sizeof(key)); 899 if (!source) { 900 key.source = SHADER_SOURCE_SOLID; 901 source_solid_color[0] = 0.0; 902 source_solid_color[1] = 0.0; 903 source_solid_color[2] = 0.0; 904 source_solid_color[3] = 0.0; 905 } 906 else if (!source->pDrawable) { 907 SourcePictPtr sp = source->pSourcePict; 908 if (sp->type == SourcePictTypeSolidFill) { 909 key.source = SHADER_SOURCE_SOLID; 910 glamor_get_rgba_from_color(&sp->solidFill.fullcolor, 911 source_solid_color); 912 } 913 else 914 goto fail; 915 } 916 else { 917 if (PICT_FORMAT_A(source->format)) 918 key.source = SHADER_SOURCE_TEXTURE_ALPHA; 919 else 920 key.source = SHADER_SOURCE_TEXTURE; 921 } 922 923 if (mask) { 924 if (!mask->pDrawable) { 925 SourcePictPtr sp = mask->pSourcePict; 926 if (sp->type == SourcePictTypeSolidFill) { 927 key.mask = SHADER_MASK_SOLID; 928 glamor_get_rgba_from_color(&sp->solidFill.fullcolor, 929 mask_solid_color); 930 } 931 else 932 goto fail; 933 } 934 else { 935 if (PICT_FORMAT_A(mask->format)) 936 key.mask = SHADER_MASK_TEXTURE_ALPHA; 937 else 938 key.mask = SHADER_MASK_TEXTURE; 939 } 940 941 if (!mask->componentAlpha) { 942 key.in = glamor_program_alpha_normal; 943 } 944 else { 945 if (op == PictOpClear) 946 key.mask = SHADER_MASK_NONE; 947 else if (glamor_priv->has_dual_blend) { 948 key.in = glamor_glsl_has_ints(glamor_priv) ? 949 glamor_program_alpha_dual_blend : 950 glamor_program_alpha_dual_blend_gles2; 951 } 952 else if (op == PictOpSrc || op == PictOpAdd 953 || op == PictOpIn || op == PictOpOut 954 || op == PictOpOverReverse) 955 key.in = glamor_program_alpha_ca_second; 956 else if (op == PictOpOutReverse || op == PictOpInReverse) { 957 key.in = glamor_program_alpha_ca_first; 958 } 959 else { 960 glamor_fallback("Unsupported component alpha op: %d\n", op); 961 goto fail; 962 } 963 } 964 } 965 else { 966 key.mask = SHADER_MASK_NONE; 967 } 968 969 if (dest_pixmap->drawable.bitsPerPixel <= 8 && 970 glamor_priv->formats[8].format == GL_RED) { 971 key.dest_swizzle = SHADER_DEST_SWIZZLE_ALPHA_TO_RED; 972 } else { 973 key.dest_swizzle = SHADER_DEST_SWIZZLE_DEFAULT; 974 } 975 976 if (source && source->alphaMap) { 977 glamor_fallback("source alphaMap\n"); 978 goto fail; 979 } 980 if (mask && mask->alphaMap) { 981 glamor_fallback("mask alphaMap\n"); 982 goto fail; 983 } 984 985 if (key.source == SHADER_SOURCE_TEXTURE || 986 key.source == SHADER_SOURCE_TEXTURE_ALPHA) { 987 if (source_pixmap == dest_pixmap) { 988 /* XXX source and the dest share the same texture. 989 * Does it need special handle? */ 990 glamor_fallback("source == dest\n"); 991 } 992 if (source_pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) { 993 source_needs_upload = TRUE; 994 } 995 } 996 997 if (key.mask == SHADER_MASK_TEXTURE || 998 key.mask == SHADER_MASK_TEXTURE_ALPHA) { 999 if (mask_pixmap == dest_pixmap) { 1000 glamor_fallback("mask == dest\n"); 1001 goto fail; 1002 } 1003 if (mask_pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED) { 1004 mask_needs_upload = TRUE; 1005 } 1006 } 1007 1008 if (source_needs_upload && mask_needs_upload 1009 && source_pixmap == mask_pixmap) { 1010 1011 if (source->format != mask->format) { 1012 saved_source_format = source->format; 1013 1014 if (!combine_pict_format(&source->format, source->format, 1015 mask->format, key.in)) { 1016 glamor_fallback("combine source %x mask %x failed.\n", 1017 source->format, mask->format); 1018 goto fail; 1019 } 1020 1021 /* XXX 1022 * By default, glamor_upload_picture_to_texture will wire alpha to 1 1023 * if one picture doesn't have alpha. So we don't do that again in 1024 * rendering function. But here is a special case, as source and 1025 * mask share the same texture but may have different formats. For 1026 * example, source doesn't have alpha, but mask has alpha. Then the 1027 * texture will have the alpha value for the mask. And will not wire 1028 * to 1 for the source. In this case, we have to use different shader 1029 * to wire the source's alpha to 1. 1030 * 1031 * But this may cause a potential problem if the source's repeat mode 1032 * is REPEAT_NONE, and if the source is smaller than the dest, then 1033 * for the region not covered by the source may be painted incorrectly. 1034 * because we wire the alpha to 1. 1035 * 1036 **/ 1037 if (!PICT_FORMAT_A(saved_source_format) 1038 && PICT_FORMAT_A(mask->format)) 1039 key.source = SHADER_SOURCE_TEXTURE; 1040 1041 if (!PICT_FORMAT_A(mask->format) 1042 && PICT_FORMAT_A(saved_source_format)) 1043 key.mask = SHADER_MASK_TEXTURE; 1044 } 1045 1046 if (!glamor_upload_picture_to_texture(source)) { 1047 glamor_fallback("Failed to upload source texture.\n"); 1048 goto fail; 1049 } 1050 mask_needs_upload = FALSE; 1051 } 1052 else { 1053 if (source_needs_upload) { 1054 if (!glamor_upload_picture_to_texture(source)) { 1055 glamor_fallback("Failed to upload source texture.\n"); 1056 goto fail; 1057 } 1058 } else { 1059 if (source && !glamor_render_format_is_supported(source)) { 1060 glamor_fallback("Unsupported source picture format.\n"); 1061 goto fail; 1062 } 1063 } 1064 1065 if (mask_needs_upload) { 1066 if (!glamor_upload_picture_to_texture(mask)) { 1067 glamor_fallback("Failed to upload mask texture.\n"); 1068 goto fail; 1069 } 1070 } else if (mask) { 1071 if (!glamor_render_format_is_supported(mask)) { 1072 glamor_fallback("Unsupported mask picture format.\n"); 1073 goto fail; 1074 } 1075 } 1076 } 1077 1078 /* If the source and mask are two differently-formatted views of 1079 * the same pixmap bits, and the pixmap was already uploaded (so 1080 * the dynamic code above doesn't apply), then fall back to 1081 * software. We should use texture views to fix this properly. 1082 */ 1083 if (source_pixmap && source_pixmap == mask_pixmap && 1084 source->format != mask->format) { 1085 goto fail; 1086 } 1087 1088 if (!glamor_set_composite_op(screen, op, op_info, dest, mask, ca_state, 1089 &key)) { 1090 goto fail; 1091 } 1092 1093 *shader = glamor_lookup_composite_shader(screen, &key); 1094 if ((*shader)->prog == 0) { 1095 glamor_fallback("no shader program for this render acccel mode\n"); 1096 goto fail; 1097 } 1098 1099 if (key.source == SHADER_SOURCE_SOLID) 1100 memcpy(&(*shader)->source_solid_color[0], 1101 source_solid_color, 4 * sizeof(float)); 1102 else { 1103 (*shader)->source_pixmap = source_pixmap; 1104 (*shader)->source = source; 1105 } 1106 1107 if (key.mask == SHADER_MASK_SOLID) 1108 memcpy(&(*shader)->mask_solid_color[0], 1109 mask_solid_color, 4 * sizeof(float)); 1110 else { 1111 (*shader)->mask_pixmap = mask_pixmap; 1112 (*shader)->mask = mask; 1113 } 1114 1115 ret = TRUE; 1116 memcpy(s_key, &key, sizeof(key)); 1117 *psaved_source_format = saved_source_format; 1118 goto done; 1119 1120 fail: 1121 if (saved_source_format) 1122 source->format = saved_source_format; 1123 done: 1124 return ret; 1125 } 1126 1127 static void 1128 glamor_composite_set_shader_blend(glamor_screen_private *glamor_priv, 1129 glamor_pixmap_private *dest_priv, 1130 struct shader_key *key, 1131 glamor_composite_shader *shader, 1132 struct blendinfo *op_info) 1133 { 1134 glamor_make_current(glamor_priv); 1135 glUseProgram(shader->prog); 1136 1137 if (key->source == SHADER_SOURCE_SOLID) { 1138 glamor_set_composite_solid(shader->source_solid_color, 1139 shader->source_uniform_location); 1140 } 1141 else { 1142 glamor_set_composite_texture(glamor_priv, 0, 1143 shader->source, 1144 shader->source_pixmap, shader->source_wh, 1145 shader->source_repeat_mode, 1146 dest_priv); 1147 } 1148 1149 if (key->mask != SHADER_MASK_NONE) { 1150 if (key->mask == SHADER_MASK_SOLID) { 1151 glamor_set_composite_solid(shader->mask_solid_color, 1152 shader->mask_uniform_location); 1153 } 1154 else { 1155 glamor_set_composite_texture(glamor_priv, 1, 1156 shader->mask, 1157 shader->mask_pixmap, shader->mask_wh, 1158 shader->mask_repeat_mode, 1159 dest_priv); 1160 } 1161 } 1162 1163 if (!glamor_priv->is_gles) 1164 glDisable(GL_COLOR_LOGIC_OP); 1165 1166 if (op_info->source_blend == GL_ONE && op_info->dest_blend == GL_ZERO) { 1167 glDisable(GL_BLEND); 1168 } 1169 else { 1170 glEnable(GL_BLEND); 1171 glBlendFunc(op_info->source_blend, op_info->dest_blend); 1172 } 1173 } 1174 1175 static Bool 1176 glamor_composite_with_shader(CARD8 op, 1177 PicturePtr source, 1178 PicturePtr mask, 1179 PicturePtr dest, 1180 PixmapPtr source_pixmap, 1181 PixmapPtr mask_pixmap, 1182 PixmapPtr dest_pixmap, 1183 glamor_pixmap_private *source_pixmap_priv, 1184 glamor_pixmap_private *mask_pixmap_priv, 1185 glamor_pixmap_private *dest_pixmap_priv, 1186 int nrect, glamor_composite_rect_t *rects, 1187 enum ca_state ca_state) 1188 { 1189 ScreenPtr screen = dest->pDrawable->pScreen; 1190 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 1191 GLfloat dst_xscale, dst_yscale; 1192 GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; 1193 struct shader_key key, key_ca; 1194 int dest_x_off, dest_y_off; 1195 int source_x_off, source_y_off; 1196 int mask_x_off, mask_y_off; 1197 PictFormatShort saved_source_format = 0; 1198 float src_matrix[9], mask_matrix[9]; 1199 float *psrc_matrix = NULL, *pmask_matrix = NULL; 1200 int nrect_max; 1201 Bool ret = FALSE; 1202 glamor_composite_shader *shader = NULL, *shader_ca = NULL; 1203 struct blendinfo op_info, op_info_ca; 1204 1205 if (!glamor_composite_choose_shader(op, source, mask, dest, 1206 source_pixmap, mask_pixmap, dest_pixmap, 1207 source_pixmap_priv, mask_pixmap_priv, 1208 dest_pixmap_priv, 1209 &key, &shader, &op_info, 1210 &saved_source_format, ca_state)) { 1211 glamor_fallback("glamor_composite_choose_shader failed\n"); 1212 goto fail; 1213 } 1214 if (ca_state == CA_TWO_PASS) { 1215 if (!glamor_composite_choose_shader(PictOpAdd, source, mask, dest, 1216 source_pixmap, mask_pixmap, dest_pixmap, 1217 source_pixmap_priv, 1218 mask_pixmap_priv, dest_pixmap_priv, 1219 &key_ca, &shader_ca, &op_info_ca, 1220 &saved_source_format, ca_state)) { 1221 glamor_fallback("glamor_composite_choose_shader failed\n"); 1222 goto fail; 1223 } 1224 } 1225 1226 glamor_make_current(glamor_priv); 1227 1228 glamor_set_destination_pixmap_priv_nc(glamor_priv, dest_pixmap, dest_pixmap_priv); 1229 glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, &key, shader, &op_info); 1230 glamor_set_alu(screen, GXcopy); 1231 1232 glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID; 1233 glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE && 1234 key.mask != SHADER_MASK_SOLID); 1235 1236 dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); 1237 dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); 1238 glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, 1239 &dest_x_off, &dest_y_off); 1240 pixmap_priv_get_dest_scale(dest_pixmap, dest_pixmap_priv, &dst_xscale, &dst_yscale); 1241 1242 if (glamor_priv->has_source_coords) { 1243 glamor_get_drawable_deltas(source->pDrawable, 1244 source_pixmap, &source_x_off, &source_y_off); 1245 pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); 1246 if (source->transform) { 1247 psrc_matrix = src_matrix; 1248 glamor_picture_get_matrixf(source, psrc_matrix); 1249 } 1250 } 1251 1252 if (glamor_priv->has_mask_coords) { 1253 glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, 1254 &mask_x_off, &mask_y_off); 1255 pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); 1256 if (mask->transform) { 1257 pmask_matrix = mask_matrix; 1258 glamor_picture_get_matrixf(mask, pmask_matrix); 1259 } 1260 } 1261 1262 nrect_max = MIN(nrect, GLAMOR_COMPOSITE_VBO_VERT_CNT / 4); 1263 1264 if (nrect < 100) { 1265 BoxRec bounds = glamor_start_rendering_bounds(); 1266 1267 for (int i = 0; i < nrect; i++) { 1268 BoxRec box = { 1269 .x1 = rects[i].x_dst, 1270 .y1 = rects[i].y_dst, 1271 .x2 = rects[i].x_dst + rects[i].width, 1272 .y2 = rects[i].y_dst + rects[i].height, 1273 }; 1274 glamor_bounds_union_box(&bounds, &box); 1275 } 1276 1277 if (bounds.x1 >= bounds.x2 || bounds.y1 >= bounds.y2) 1278 goto disable_va; 1279 1280 glEnable(GL_SCISSOR_TEST); 1281 glScissor(bounds.x1 + dest_x_off, 1282 bounds.y1 + dest_y_off, 1283 bounds.x2 - bounds.x1, 1284 bounds.y2 - bounds.y1); 1285 } 1286 1287 while (nrect) { 1288 int mrect, rect_processed; 1289 int vb_stride; 1290 float *vertices; 1291 1292 mrect = nrect > nrect_max ? nrect_max : nrect; 1293 vertices = glamor_setup_composite_vbo(screen, mrect * 4); 1294 rect_processed = mrect; 1295 vb_stride = glamor_priv->vb_stride / sizeof(float); 1296 while (mrect--) { 1297 INT16 x_source; 1298 INT16 y_source; 1299 INT16 x_mask; 1300 INT16 y_mask; 1301 INT16 x_dest; 1302 INT16 y_dest; 1303 CARD16 width; 1304 CARD16 height; 1305 1306 x_dest = rects->x_dst + dest_x_off; 1307 y_dest = rects->y_dst + dest_y_off; 1308 x_source = rects->x_src + source_x_off; 1309 y_source = rects->y_src + source_y_off; 1310 x_mask = rects->x_mask + mask_x_off; 1311 y_mask = rects->y_mask + mask_y_off; 1312 width = rects->width; 1313 height = rects->height; 1314 1315 DEBUGF 1316 ("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n", 1317 x_dest, y_dest, x_source, y_source, x_mask, y_mask, width, 1318 height); 1319 1320 glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale, 1321 dst_yscale, x_dest, y_dest, 1322 x_dest + width, y_dest + height, 1323 vertices, 1324 vb_stride); 1325 vertices += 2; 1326 if (key.source != SHADER_SOURCE_SOLID) { 1327 glamor_set_normalize_tcoords_generic(source_pixmap, 1328 source_pixmap_priv, 1329 source->repeatType, 1330 psrc_matrix, src_xscale, 1331 src_yscale, x_source, 1332 y_source, x_source + width, 1333 y_source + height, 1334 vertices, vb_stride); 1335 vertices += 2; 1336 } 1337 1338 if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { 1339 glamor_set_normalize_tcoords_generic(mask_pixmap, 1340 mask_pixmap_priv, 1341 mask->repeatType, 1342 pmask_matrix, mask_xscale, 1343 mask_yscale, x_mask, 1344 y_mask, x_mask + width, 1345 y_mask + height, 1346 vertices, vb_stride); 1347 vertices += 2; 1348 } 1349 glamor_priv->render_nr_quads++; 1350 rects++; 1351 1352 /* We've incremented by one of our 4 verts, now do the other 3. */ 1353 vertices += 3 * vb_stride; 1354 } 1355 glamor_put_vbo_space(screen); 1356 glamor_flush_composite_rects(screen); 1357 nrect -= rect_processed; 1358 if (ca_state == CA_TWO_PASS) { 1359 glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, 1360 &key_ca, shader_ca, &op_info_ca); 1361 glamor_flush_composite_rects(screen); 1362 if (nrect) 1363 glamor_composite_set_shader_blend(glamor_priv, dest_pixmap_priv, 1364 &key, shader, &op_info); 1365 } 1366 } 1367 1368 glDisable(GL_SCISSOR_TEST); 1369 disable_va: 1370 glDisableVertexAttribArray(GLAMOR_VERTEX_POS); 1371 glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); 1372 glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); 1373 glDisable(GL_BLEND); 1374 DEBUGF("finish rendering.\n"); 1375 if (saved_source_format) 1376 source->format = saved_source_format; 1377 1378 ret = TRUE; 1379 1380 fail: 1381 if (mask_pixmap && glamor_pixmap_is_memory(mask_pixmap)) 1382 glamor_pixmap_destroy_fbo(mask_pixmap); 1383 if (source_pixmap && glamor_pixmap_is_memory(source_pixmap)) 1384 glamor_pixmap_destroy_fbo(source_pixmap); 1385 1386 return ret; 1387 } 1388 1389 static PicturePtr 1390 glamor_convert_gradient_picture(ScreenPtr screen, 1391 PicturePtr source, 1392 int x_source, 1393 int y_source, int width, int height) 1394 { 1395 PixmapPtr pixmap; 1396 PicturePtr dst = NULL; 1397 int error; 1398 PictFormatPtr pFormat; 1399 PictFormatShort format; 1400 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 1401 1402 if (source->pDrawable) { 1403 pFormat = source->pFormat; 1404 format = pFormat->format; 1405 } else { 1406 format = PICT_a8r8g8b8; 1407 pFormat = PictureMatchFormat(screen, 32, format); 1408 } 1409 1410 if (glamor_priv->enable_gradient_shader && !source->pDrawable) { 1411 if (source->pSourcePict->type == SourcePictTypeLinear) { 1412 dst = glamor_generate_linear_gradient_picture(screen, 1413 source, x_source, 1414 y_source, width, 1415 height, format); 1416 } 1417 else if (source->pSourcePict->type == SourcePictTypeRadial) { 1418 dst = glamor_generate_radial_gradient_picture(screen, 1419 source, x_source, 1420 y_source, width, 1421 height, format); 1422 } 1423 1424 if (dst) { 1425 return dst; 1426 } 1427 } 1428 1429 pixmap = glamor_create_pixmap(screen, 1430 width, 1431 height, 1432 PIXMAN_FORMAT_DEPTH(format), 1433 GLAMOR_CREATE_PIXMAP_CPU); 1434 1435 if (!pixmap) 1436 return NULL; 1437 1438 dst = CreatePicture(0, 1439 &pixmap->drawable, pFormat, 0, 0, serverClient, &error); 1440 glamor_destroy_pixmap(pixmap); 1441 if (!dst) 1442 return NULL; 1443 1444 ValidatePicture(dst); 1445 1446 fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source, 1447 0, 0, 0, 0, width, height); 1448 return dst; 1449 } 1450 1451 Bool 1452 glamor_composite_clipped_region(CARD8 op, 1453 PicturePtr source, 1454 PicturePtr mask, 1455 PicturePtr dest, 1456 PixmapPtr source_pixmap, 1457 PixmapPtr mask_pixmap, 1458 PixmapPtr dest_pixmap, 1459 RegionPtr region, 1460 int x_source, 1461 int y_source, 1462 int x_mask, int y_mask, int x_dest, int y_dest) 1463 { 1464 glamor_pixmap_private *source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); 1465 glamor_pixmap_private *mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); 1466 glamor_pixmap_private *dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); 1467 glamor_screen_private *glamor_priv = glamor_get_screen_private(dest_pixmap->drawable.pScreen); 1468 ScreenPtr screen = dest->pDrawable->pScreen; 1469 PicturePtr temp_src = source, temp_mask = mask; 1470 PixmapPtr temp_src_pixmap = source_pixmap; 1471 PixmapPtr temp_mask_pixmap = mask_pixmap; 1472 glamor_pixmap_private *temp_src_priv = source_pixmap_priv; 1473 glamor_pixmap_private *temp_mask_priv = mask_pixmap_priv; 1474 int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; 1475 BoxPtr extent; 1476 glamor_composite_rect_t rect[10]; 1477 glamor_composite_rect_t *prect = rect; 1478 int prect_size = ARRAY_SIZE(rect); 1479 int ok = FALSE; 1480 int i; 1481 int width; 1482 int height; 1483 BoxPtr box; 1484 int nbox; 1485 enum ca_state ca_state = CA_NONE; 1486 1487 extent = RegionExtents(region); 1488 box = RegionRects(region); 1489 nbox = RegionNumRects(region); 1490 width = extent->x2 - extent->x1; 1491 height = extent->y2 - extent->y1; 1492 1493 x_temp_src = x_source; 1494 y_temp_src = y_source; 1495 x_temp_mask = x_mask; 1496 y_temp_mask = y_mask; 1497 1498 DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", 1499 x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); 1500 1501 /* Is the composite operation equivalent to a copy? */ 1502 if (source && 1503 !mask && !source->alphaMap && !dest->alphaMap 1504 && source->pDrawable && !source->transform 1505 /* CopyArea is only defined with matching depths. */ 1506 && dest->pDrawable->depth == source->pDrawable->depth 1507 && ((op == PictOpSrc 1508 && (source->format == dest->format 1509 || (PICT_FORMAT_COLOR(dest->format) 1510 && PICT_FORMAT_COLOR(source->format) 1511 && dest->format == PICT_FORMAT(PICT_FORMAT_BPP(source->format), 1512 PICT_FORMAT_TYPE(source->format), 1513 0, 1514 PICT_FORMAT_R(source->format), 1515 PICT_FORMAT_G(source->format), 1516 PICT_FORMAT_B(source->format))))) 1517 || (op == PictOpOver 1518 && source->format == dest->format 1519 && !PICT_FORMAT_A(source->format))) 1520 && x_source >= 0 && y_source >= 0 1521 && (x_source + width) <= source->pDrawable->width 1522 && (y_source + height) <= source->pDrawable->height) { 1523 x_source += source->pDrawable->x; 1524 y_source += source->pDrawable->y; 1525 x_dest += dest->pDrawable->x; 1526 y_dest += dest->pDrawable->y; 1527 glamor_copy(source->pDrawable, dest->pDrawable, NULL, 1528 box, nbox, x_source - x_dest, 1529 y_source - y_dest, FALSE, FALSE, 0, NULL); 1530 ok = TRUE; 1531 goto out; 1532 } 1533 1534 /* XXX is it possible source mask have non-zero drawable.x/y? */ 1535 if (source 1536 && ((!source->pDrawable 1537 && (source->pSourcePict->type != SourcePictTypeSolidFill)) 1538 || (source->pDrawable && source_pixmap 1539 && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) 1540 && (source_pixmap->drawable.width != width 1541 || source_pixmap->drawable.height != height)))) { 1542 temp_src = 1543 glamor_convert_gradient_picture(screen, source, 1544 extent->x1 + x_source - x_dest - dest->pDrawable->x, 1545 extent->y1 + y_source - y_dest - dest->pDrawable->y, 1546 width, height); 1547 if (!temp_src) { 1548 temp_src = source; 1549 goto out; 1550 } 1551 temp_src_pixmap = (PixmapPtr) (temp_src->pDrawable); 1552 temp_src_priv = glamor_get_pixmap_private(temp_src_pixmap); 1553 x_temp_src = -extent->x1 + x_dest + dest->pDrawable->x; 1554 y_temp_src = -extent->y1 + y_dest + dest->pDrawable->y; 1555 } 1556 1557 if (mask 1558 && 1559 ((!mask->pDrawable 1560 && (mask->pSourcePict->type != SourcePictTypeSolidFill)) 1561 || (mask->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv) 1562 && (mask_pixmap->drawable.width != width 1563 || mask_pixmap->drawable.height != height)))) { 1564 /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity 1565 * to do reduce one conversion. */ 1566 temp_mask = 1567 glamor_convert_gradient_picture(screen, mask, 1568 extent->x1 + x_mask - x_dest - dest->pDrawable->x, 1569 extent->y1 + y_mask - y_dest - dest->pDrawable->y, 1570 width, height); 1571 if (!temp_mask) { 1572 temp_mask = mask; 1573 goto out; 1574 } 1575 temp_mask_pixmap = (PixmapPtr) (temp_mask->pDrawable); 1576 temp_mask_priv = glamor_get_pixmap_private(temp_mask_pixmap); 1577 x_temp_mask = -extent->x1 + x_dest + dest->pDrawable->x; 1578 y_temp_mask = -extent->y1 + y_dest + dest->pDrawable->y; 1579 } 1580 1581 if (mask && mask->componentAlpha) { 1582 if (glamor_priv->has_dual_blend) { 1583 ca_state = CA_DUAL_BLEND; 1584 } else { 1585 if (op == PictOpOver) { 1586 if (glamor_pixmap_is_memory(mask_pixmap)) { 1587 glamor_fallback("two pass not supported on memory pximaps\n"); 1588 goto out; 1589 } 1590 ca_state = CA_TWO_PASS; 1591 op = PictOpOutReverse; 1592 } 1593 } 1594 } 1595 1596 if (temp_src_pixmap == dest_pixmap) { 1597 glamor_fallback("source and dest pixmaps are the same\n"); 1598 goto out; 1599 } 1600 if (temp_mask_pixmap == dest_pixmap) { 1601 glamor_fallback("mask and dest pixmaps are the same\n"); 1602 goto out; 1603 } 1604 1605 x_dest += dest->pDrawable->x; 1606 y_dest += dest->pDrawable->y; 1607 if (temp_src && temp_src->pDrawable) { 1608 x_temp_src += temp_src->pDrawable->x; 1609 y_temp_src += temp_src->pDrawable->y; 1610 } 1611 if (temp_mask && temp_mask->pDrawable) { 1612 x_temp_mask += temp_mask->pDrawable->x; 1613 y_temp_mask += temp_mask->pDrawable->y; 1614 } 1615 1616 if (nbox > ARRAY_SIZE(rect)) { 1617 prect = calloc(nbox, sizeof(*prect)); 1618 if (prect) 1619 prect_size = nbox; 1620 else { 1621 prect = rect; 1622 prect_size = ARRAY_SIZE(rect); 1623 } 1624 } 1625 while (nbox) { 1626 int box_cnt; 1627 1628 box_cnt = nbox > prect_size ? prect_size : nbox; 1629 for (i = 0; i < box_cnt; i++) { 1630 prect[i].x_src = box[i].x1 + x_temp_src - x_dest; 1631 prect[i].y_src = box[i].y1 + y_temp_src - y_dest; 1632 prect[i].x_mask = box[i].x1 + x_temp_mask - x_dest; 1633 prect[i].y_mask = box[i].y1 + y_temp_mask - y_dest; 1634 prect[i].x_dst = box[i].x1; 1635 prect[i].y_dst = box[i].y1; 1636 prect[i].width = box[i].x2 - box[i].x1; 1637 prect[i].height = box[i].y2 - box[i].y1; 1638 DEBUGF("dest %d %d \n", prect[i].x_dst, prect[i].y_dst); 1639 } 1640 ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest, 1641 temp_src_pixmap, temp_mask_pixmap, dest_pixmap, 1642 temp_src_priv, temp_mask_priv, 1643 dest_pixmap_priv, 1644 box_cnt, prect, ca_state); 1645 if (!ok) 1646 break; 1647 nbox -= box_cnt; 1648 box += box_cnt; 1649 } 1650 1651 if (prect != rect) 1652 free(prect); 1653 out: 1654 if (temp_src != source) 1655 FreePicture(temp_src, 0); 1656 if (temp_mask != mask) 1657 FreePicture(temp_mask, 0); 1658 1659 return ok; 1660 } 1661 1662 void 1663 glamor_composite(CARD8 op, 1664 PicturePtr source, 1665 PicturePtr mask, 1666 PicturePtr dest, 1667 INT16 x_source, 1668 INT16 y_source, 1669 INT16 x_mask, 1670 INT16 y_mask, 1671 INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) 1672 { 1673 ScreenPtr screen = dest->pDrawable->pScreen; 1674 PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); 1675 PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; 1676 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 1677 RegionRec region; 1678 BoxPtr extent; 1679 int nbox, ok = FALSE; 1680 int force_clip = 0; 1681 1682 if (source->pDrawable) { 1683 source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); 1684 if (glamor_pixmap_drm_only(source_pixmap)) 1685 goto fail; 1686 } 1687 1688 if (mask && mask->pDrawable) { 1689 mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); 1690 if (glamor_pixmap_drm_only(mask_pixmap)) 1691 goto fail; 1692 } 1693 1694 DEBUGF 1695 ("source pixmap %p (%d %d) mask(%d %d) dest(%d %d) width %d height %d \n", 1696 source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest, 1697 width, height); 1698 1699 if (!glamor_pixmap_has_fbo(dest_pixmap)) 1700 goto fail; 1701 1702 if (op >= ARRAY_SIZE(composite_op_info)) { 1703 glamor_fallback("Unsupported composite op %x\n", op); 1704 goto fail; 1705 } 1706 1707 if (mask && mask->componentAlpha && !glamor_priv->has_dual_blend) { 1708 if (op == PictOpAtop 1709 || op == PictOpAtopReverse 1710 || op == PictOpXor || op >= PictOpSaturate) { 1711 glamor_fallback("glamor_composite(): component alpha op %x\n", op); 1712 goto fail; 1713 } 1714 } 1715 1716 if ((source && source->filter >= PictFilterConvolution) 1717 || (mask && mask->filter >= PictFilterConvolution)) { 1718 glamor_fallback("glamor_composite(): unsupported filter\n"); 1719 goto fail; 1720 } 1721 1722 if (!miComputeCompositeRegion(®ion, 1723 source, mask, dest, 1724 x_source + 1725 (source_pixmap ? source->pDrawable->x : 0), 1726 y_source + 1727 (source_pixmap ? source->pDrawable->y : 0), 1728 x_mask + 1729 (mask_pixmap ? mask->pDrawable->x : 0), 1730 y_mask + 1731 (mask_pixmap ? mask->pDrawable->y : 0), 1732 x_dest + dest->pDrawable->x, 1733 y_dest + dest->pDrawable->y, width, height)) { 1734 return; 1735 } 1736 1737 nbox = REGION_NUM_RECTS(®ion); 1738 DEBUGF("first clipped when compositing.\n"); 1739 DEBUGRegionPrint(®ion); 1740 extent = RegionExtents(®ion); 1741 if (nbox == 0) 1742 return; 1743 1744 /* If destination is not a large pixmap, but the region is larger 1745 * than texture size limitation, and source or mask is memory pixmap, 1746 * then there may be need to load a large memory pixmap to a 1747 * texture, and this is not permitted. Then we force to clip the 1748 * destination and make sure latter will not upload a large memory 1749 * pixmap. */ 1750 if (!glamor_check_fbo_size(glamor_priv, 1751 extent->x2 - extent->x1, extent->y2 - extent->y1) 1752 && glamor_pixmap_is_large(dest_pixmap) 1753 && ((source_pixmap 1754 && (glamor_pixmap_is_memory(source_pixmap) || 1755 source->repeatType == RepeatPad)) 1756 || (mask_pixmap && 1757 (glamor_pixmap_is_memory(mask_pixmap) || 1758 mask->repeatType == RepeatPad)) 1759 || (!source_pixmap && 1760 (source->pSourcePict->type != SourcePictTypeSolidFill)) 1761 || (!mask_pixmap && mask && 1762 mask->pSourcePict->type != SourcePictTypeSolidFill))) 1763 force_clip = 1; 1764 1765 if (force_clip || glamor_pixmap_is_large(dest_pixmap) 1766 || (source_pixmap 1767 && glamor_pixmap_is_large(source_pixmap)) 1768 || (mask_pixmap && glamor_pixmap_is_large(mask_pixmap))) 1769 ok = glamor_composite_largepixmap_region(op, 1770 source, mask, dest, 1771 source_pixmap, 1772 mask_pixmap, 1773 dest_pixmap, 1774 ®ion, force_clip, 1775 x_source, y_source, 1776 x_mask, y_mask, 1777 x_dest, y_dest, width, height); 1778 else 1779 ok = glamor_composite_clipped_region(op, source, 1780 mask, dest, 1781 source_pixmap, 1782 mask_pixmap, 1783 dest_pixmap, 1784 ®ion, 1785 x_source, y_source, 1786 x_mask, y_mask, x_dest, y_dest); 1787 1788 REGION_UNINIT(dest->pDrawable->pScreen, ®ion); 1789 1790 if (ok) 1791 return; 1792 1793 fail: 1794 1795 glamor_fallback 1796 ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", 1797 source, source->pDrawable, 1798 source->pDrawable ? source->pDrawable->width : 0, 1799 source->pDrawable ? source->pDrawable->height : 0, mask, 1800 (!mask) ? NULL : mask->pDrawable, 1801 (!mask || !mask->pDrawable) ? 0 : mask->pDrawable->width, 1802 (!mask || !mask->pDrawable) ? 0 : mask->pDrawable->height, 1803 glamor_get_picture_location(source), 1804 glamor_get_picture_location(mask), 1805 dest, dest->pDrawable, 1806 dest->pDrawable->width, dest->pDrawable->height, 1807 glamor_get_picture_location(dest)); 1808 1809 if (glamor_prepare_access_picture_box(dest, GLAMOR_ACCESS_RW, 1810 x_dest, y_dest, width, height) && 1811 glamor_prepare_access_picture_box(source, GLAMOR_ACCESS_RO, 1812 x_source, y_source, width, height) && 1813 glamor_prepare_access_picture_box(mask, GLAMOR_ACCESS_RO, 1814 x_mask, y_mask, width, height)) 1815 { 1816 fbComposite(op, 1817 source, mask, dest, 1818 x_source, y_source, 1819 x_mask, y_mask, x_dest, y_dest, width, height); 1820 } 1821 glamor_finish_access_picture(mask); 1822 glamor_finish_access_picture(source); 1823 glamor_finish_access_picture(dest); 1824 } 1825