xserver

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

glamor_render.c (64923B)


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