Home | History | Annotate | Line # | Download | only in glamor
      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(&region,
   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(&region);
   1738     DEBUGF("first clipped when compositing.\n");
   1739     DEBUGRegionPrint(&region);
   1740     extent = RegionExtents(&region);
   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                                                  &region, 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                                              &region,
   1785                                              x_source, y_source,
   1786                                              x_mask, y_mask, x_dest, y_dest);
   1787 
   1788     REGION_UNINIT(dest->pDrawable->pScreen, &region);
   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