diff options
Diffstat (limited to 'xorg-server/glamor/glamor_render.c')
-rw-r--r-- | xorg-server/glamor/glamor_render.c | 3724 |
1 files changed, 1861 insertions, 1863 deletions
diff --git a/xorg-server/glamor/glamor_render.c b/xorg-server/glamor/glamor_render.c index 76a571f8b..4a3a97ccd 100644 --- a/xorg-server/glamor/glamor_render.c +++ b/xorg-server/glamor/glamor_render.c @@ -45,1425 +45,1428 @@ #endif static struct blendinfo composite_op_info[] = { - [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, - [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, - [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, - [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, - [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, - [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, - [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, - [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, - [PictOpXor] = - {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, - [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, + [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, + [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, + [PictOpDst] = {0, 0, GL_ZERO, GL_ONE}, + [PictOpOver] = {0, 1, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpOverReverse] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ONE}, + [PictOpIn] = {1, 0, GL_DST_ALPHA, GL_ZERO}, + [PictOpInReverse] = {0, 1, GL_ZERO, GL_SRC_ALPHA}, + [PictOpOut] = {1, 0, GL_ONE_MINUS_DST_ALPHA, GL_ZERO}, + [PictOpOutReverse] = {0, 1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtop] = {1, 1, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAtopReverse] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA}, + [PictOpXor] = {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, + [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, }; + #define RepeatFix 10 static GLuint -glamor_create_composite_fs(glamor_gl_dispatch * dispatch, - struct shader_key *key) +glamor_create_composite_fs(glamor_gl_dispatch *dispatch, + struct shader_key *key) { - const char *repeat_define = - "#define RepeatNone 0\n" - "#define RepeatNormal 1\n" - "#define RepeatPad 2\n" - "#define RepeatReflect 3\n" - "#define RepeatFix 10\n" - "uniform int source_repeat_mode;\n" - "uniform int mask_repeat_mode;\n"; - const char *relocate_texture = - GLAMOR_DEFAULT_PRECISION - "vec2 rel_tex_coord(vec2 texture, vec4 wh, int repeat) \n" - "{\n" - " vec2 rel_tex; \n" - " rel_tex = texture * wh.xy; \n" - " if (repeat == RepeatNone)\n" - " return rel_tex; \n" - " else if (repeat == RepeatNormal) \n" - " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh.xy); \n" - " else if(repeat == RepeatPad) { \n" - " if (rel_tex.x >= 1.0) rel_tex.x = 1.0 - wh.z * wh.x / 2.; \n" - " else if(rel_tex.x < 0.0) rel_tex.x = 0.0; \n" - " if (rel_tex.y >= 1.0) rel_tex.y = 1.0 - wh.w * wh.y / 2.; \n" - " else if(rel_tex.y < 0.0) rel_tex.y = 0.0; \n" - " rel_tex = rel_tex / wh.xy; \n" - " } \n" - " else if(repeat == RepeatReflect) {\n" - " if ((1.0 - mod(abs(floor(rel_tex.x)), 2.0)) < 0.001)\n" - " rel_tex.x = 2.0 - (1.0 - fract(rel_tex.x))/wh.x;\n" - " else \n" - " rel_tex.x = fract(rel_tex.x)/wh.x;\n" - " if ((1.0 - mod(abs(floor(rel_tex.y)), 2.0)) < 0.001)\n" - " rel_tex.y = 2.0 - (1.0 - fract(rel_tex.y))/wh.y;\n" - " else \n" - " rel_tex.y = fract(rel_tex.y)/wh.y;\n" - " } \n" - " return rel_tex; \n" - "}\n"; - /* The texture and the pixmap size is not match eaxctly, so can't sample it directly. - * rel_sampler will recalculate the texture coords.*/ - const char *rel_sampler = - " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec4 wh, int repeat, int set_alpha)\n" - "{\n" - " tex = rel_tex_coord(tex, wh, repeat - RepeatFix);\n" - " if (repeat == RepeatFix) {\n" - " if (!(tex.x >= 0.0 && tex.x < 1.0 \n" - " && tex.y >= 0.0 && tex.y < 1.0))\n" - " return vec4(0.0, 0.0, 0.0, set_alpha);\n" - " tex = (fract(tex) / wh.xy);\n" - " }\n" - " if (set_alpha != 1)\n" - " return texture2D(tex_image, tex);\n" - " else\n" - " return vec4(texture2D(tex_image, tex).rgb, 1.0);\n" - "}\n"; - - const char *source_solid_fetch = - GLAMOR_DEFAULT_PRECISION - "uniform vec4 source;\n" - "vec4 get_source()\n" "{\n" " return source;\n" "}\n"; - const char *source_alpha_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION - "varying vec2 source_texture;\n" - "uniform sampler2D source_sampler;\n" - "uniform vec4 source_wh;" - "vec4 get_source()\n" - "{\n" - " if (source_repeat_mode < RepeatFix)\n" - " return texture2D(source_sampler, source_texture);\n" - " else \n" - " return rel_sampler(source_sampler, source_texture,\n" - " source_wh, source_repeat_mode, 0);\n" - "}\n"; - const char *source_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" - "uniform sampler2D source_sampler;\n" - "uniform vec4 source_wh;\n" - "vec4 get_source()\n" - "{\n" - " if (source_repeat_mode < RepeatFix) \n" - " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" - " else \n" - " return rel_sampler(source_sampler, source_texture,\n" - " source_wh, source_repeat_mode, 1);\n" - "}\n"; - const char *mask_solid_fetch = - GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" - "vec4 get_mask()\n" "{\n" " return mask;\n" "}\n"; - const char *mask_alpha_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" - "uniform sampler2D mask_sampler;\n" - "uniform vec4 mask_wh;\n" - "vec4 get_mask()\n" - "{\n" - " if (mask_repeat_mode < RepeatFix) \n" - " return texture2D(mask_sampler, mask_texture);\n" - " else \n" - " return rel_sampler(mask_sampler, mask_texture,\n" - " mask_wh, mask_repeat_mode, 0);\n" - "}\n"; - const char *mask_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" - "uniform sampler2D mask_sampler;\n" - "uniform vec4 mask_wh;\n" - "vec4 get_mask()\n" - "{\n" - " if (mask_repeat_mode < RepeatFix) \n" - " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" - " else \n" - " return rel_sampler(mask_sampler, mask_texture,\n" - " mask_wh, mask_repeat_mode, 1);\n" - "}\n"; - const char *in_source_only = - GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" - " gl_FragColor = get_source();\n" "}\n"; - const char *in_normal = - GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" - " gl_FragColor = get_source() * get_mask().a;\n" "}\n"; - const char *in_ca_source = - GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" - " gl_FragColor = get_source() * get_mask();\n" "}\n"; - const char *in_ca_alpha = - GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" - " gl_FragColor = get_source().a * get_mask();\n" "}\n"; - char *source; - const char *source_fetch; - const char *mask_fetch = ""; - const char *in; - GLuint prog; - - switch (key->source) { - case SHADER_SOURCE_SOLID: - source_fetch = source_solid_fetch; - break; - case SHADER_SOURCE_TEXTURE_ALPHA: - source_fetch = source_alpha_pixmap_fetch; - break; - case SHADER_SOURCE_TEXTURE: - source_fetch = source_pixmap_fetch; - break; - default: - FatalError("Bad composite shader source"); - } - - switch (key->mask) { - case SHADER_MASK_NONE: - break; - case SHADER_MASK_SOLID: - mask_fetch = mask_solid_fetch; - break; - case SHADER_MASK_TEXTURE_ALPHA: - mask_fetch = mask_alpha_pixmap_fetch; - break; - case SHADER_MASK_TEXTURE: - mask_fetch = mask_pixmap_fetch; - break; - default: - FatalError("Bad composite shader mask"); - } - - switch (key->in) { - case SHADER_IN_SOURCE_ONLY: - in = in_source_only; - break; - case SHADER_IN_NORMAL: - in = in_normal; - break; - case SHADER_IN_CA_SOURCE: - in = in_ca_source; - break; - case SHADER_IN_CA_ALPHA: - in = in_ca_alpha; - break; - default: - FatalError("Bad composite IN type"); - } - - XNFasprintf(&source, "%s%s%s%s%s%s", repeat_define, relocate_texture, rel_sampler,source_fetch, mask_fetch, in); - - - prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - source); - free(source); - - return prog; + const char *repeat_define = + "#define RepeatNone 0\n" + "#define RepeatNormal 1\n" + "#define RepeatPad 2\n" + "#define RepeatReflect 3\n" + "#define RepeatFix 10\n" + "uniform int source_repeat_mode;\n" + "uniform int mask_repeat_mode;\n"; + const char *relocate_texture = + GLAMOR_DEFAULT_PRECISION + "vec2 rel_tex_coord(vec2 texture, vec4 wh, int repeat) \n" + "{\n" + " vec2 rel_tex; \n" + " rel_tex = texture * wh.xy; \n" + " if (repeat == RepeatNone)\n" + " return rel_tex; \n" + " else if (repeat == RepeatNormal) \n" + " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh.xy); \n" + " else if(repeat == RepeatPad) { \n" + " if (rel_tex.x >= 1.0) rel_tex.x = 1.0 - wh.z * wh.x / 2.; \n" + " else if(rel_tex.x < 0.0) rel_tex.x = 0.0; \n" + " if (rel_tex.y >= 1.0) rel_tex.y = 1.0 - wh.w * wh.y / 2.; \n" + " else if(rel_tex.y < 0.0) rel_tex.y = 0.0; \n" + " rel_tex = rel_tex / wh.xy; \n" + " } \n" + " else if(repeat == RepeatReflect) {\n" + " if ((1.0 - mod(abs(floor(rel_tex.x)), 2.0)) < 0.001)\n" + " rel_tex.x = 2.0 - (1.0 - fract(rel_tex.x))/wh.x;\n" + " else \n" + " rel_tex.x = fract(rel_tex.x)/wh.x;\n" + " if ((1.0 - mod(abs(floor(rel_tex.y)), 2.0)) < 0.001)\n" + " rel_tex.y = 2.0 - (1.0 - fract(rel_tex.y))/wh.y;\n" + " else \n" + " rel_tex.y = fract(rel_tex.y)/wh.y;\n" + " } \n" + " return rel_tex; \n" + "}\n"; + /* The texture and the pixmap size is not match eaxctly, so can't sample it directly. + * rel_sampler will recalculate the texture coords.*/ + const char *rel_sampler = + " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec4 wh, int repeat, int set_alpha)\n" + "{\n" + " tex = rel_tex_coord(tex, wh, repeat - RepeatFix);\n" + " if (repeat == RepeatFix) {\n" + " if (!(tex.x >= 0.0 && tex.x < 1.0 \n" + " && tex.y >= 0.0 && tex.y < 1.0))\n" + " return vec4(0.0, 0.0, 0.0, set_alpha);\n" + " tex = (fract(tex) / wh.xy);\n" + " }\n" + " if (set_alpha != 1)\n" + " return texture2D(tex_image, tex);\n" + " else\n" + " return vec4(texture2D(tex_image, tex).rgb, 1.0);\n" + "}\n"; + + const char *source_solid_fetch = + GLAMOR_DEFAULT_PRECISION + "uniform vec4 source;\n" + "vec4 get_source()\n" + "{\n" + " return source;\n" + "}\n"; + const char *source_alpha_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION + "varying vec2 source_texture;\n" + "uniform sampler2D source_sampler;\n" + "uniform vec4 source_wh;" + "vec4 get_source()\n" + "{\n" + " if (source_repeat_mode < RepeatFix)\n" + " return texture2D(source_sampler, source_texture);\n" + " else \n" + " return rel_sampler(source_sampler, source_texture,\n" + " source_wh, source_repeat_mode, 0);\n" + "}\n"; + const char *source_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION + "varying vec2 source_texture;\n" + "uniform sampler2D source_sampler;\n" + "uniform vec4 source_wh;\n" + "vec4 get_source()\n" + "{\n" + " if (source_repeat_mode < RepeatFix) \n" + " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" + " else \n" + " return rel_sampler(source_sampler, source_texture,\n" + " source_wh, source_repeat_mode, 1);\n" + "}\n"; + const char *mask_solid_fetch = + GLAMOR_DEFAULT_PRECISION + "uniform vec4 mask;\n" + "vec4 get_mask()\n" + "{\n" + " return mask;\n" + "}\n"; + const char *mask_alpha_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION + "varying vec2 mask_texture;\n" + "uniform sampler2D mask_sampler;\n" + "uniform vec4 mask_wh;\n" + "vec4 get_mask()\n" + "{\n" + " if (mask_repeat_mode < RepeatFix) \n" + " return texture2D(mask_sampler, mask_texture);\n" + " else \n" + " return rel_sampler(mask_sampler, mask_texture,\n" + " mask_wh, mask_repeat_mode, 0);\n" + "}\n"; + const char *mask_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION + "varying vec2 mask_texture;\n" + "uniform sampler2D mask_sampler;\n" + "uniform vec4 mask_wh;\n" + "vec4 get_mask()\n" + "{\n" + " if (mask_repeat_mode < RepeatFix) \n" + " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" + " else \n" + " return rel_sampler(mask_sampler, mask_texture,\n" + " mask_wh, mask_repeat_mode, 1);\n" + "}\n"; + const char *in_source_only = + GLAMOR_DEFAULT_PRECISION + "void main()\n" + "{\n" + " gl_FragColor = get_source();\n" + "}\n"; + const char *in_normal = + GLAMOR_DEFAULT_PRECISION + "void main()\n" + "{\n" + " gl_FragColor = get_source() * get_mask().a;\n" + "}\n"; + const char *in_ca_source = + GLAMOR_DEFAULT_PRECISION + "void main()\n" + "{\n" + " gl_FragColor = get_source() * get_mask();\n" + "}\n"; + const char *in_ca_alpha = + GLAMOR_DEFAULT_PRECISION + "void main()\n" + "{\n" + " gl_FragColor = get_source().a * get_mask();\n" + "}\n"; + char *source; + const char *source_fetch; + const char *mask_fetch = ""; + const char *in; + GLuint prog; + + switch (key->source) { + case SHADER_SOURCE_SOLID: + source_fetch = source_solid_fetch; + break; + case SHADER_SOURCE_TEXTURE_ALPHA: + source_fetch = source_alpha_pixmap_fetch; + break; + case SHADER_SOURCE_TEXTURE: + source_fetch = source_pixmap_fetch; + break; + default: + FatalError("Bad composite shader source"); + } + + switch (key->mask) { + case SHADER_MASK_NONE: + break; + case SHADER_MASK_SOLID: + mask_fetch = mask_solid_fetch; + break; + case SHADER_MASK_TEXTURE_ALPHA: + mask_fetch = mask_alpha_pixmap_fetch; + break; + case SHADER_MASK_TEXTURE: + mask_fetch = mask_pixmap_fetch; + break; + default: + FatalError("Bad composite shader mask"); + } + + switch (key->in) { + case SHADER_IN_SOURCE_ONLY: + in = in_source_only; + break; + case SHADER_IN_NORMAL: + in = in_normal; + break; + case SHADER_IN_CA_SOURCE: + in = in_ca_source; + break; + case SHADER_IN_CA_ALPHA: + in = in_ca_alpha; + break; + default: + FatalError("Bad composite IN type"); + } + + XNFasprintf(&source, "%s%s%s%s%s%s", repeat_define, relocate_texture, + rel_sampler, source_fetch, mask_fetch, in); + + prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, source); + free(source); + + return prog; } static GLuint -glamor_create_composite_vs(glamor_gl_dispatch * dispatch, - struct shader_key *key) +glamor_create_composite_vs(glamor_gl_dispatch *dispatch, + struct shader_key *key) { - const char *main_opening = - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord0;\n" - "attribute vec4 v_texcoord1;\n" - "varying vec2 source_texture;\n" - "varying vec2 mask_texture;\n" - "void main()\n" "{\n" " gl_Position = v_position;\n"; - const char *source_coords = - " source_texture = v_texcoord0.xy;\n"; - const char *mask_coords = " mask_texture = v_texcoord1.xy;\n"; - const char *main_closing = "}\n"; - const char *source_coords_setup = ""; - const char *mask_coords_setup = ""; - char *source; - GLuint prog; - - if (key->source != SHADER_SOURCE_SOLID) - source_coords_setup = source_coords; - - if (key->mask != SHADER_MASK_NONE - && key->mask != SHADER_MASK_SOLID) - mask_coords_setup = mask_coords; - - XNFasprintf(&source, - "%s%s%s%s", - main_opening, - source_coords_setup, mask_coords_setup, main_closing); - - prog = - glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, source); - free(source); - - return prog; + const char *main_opening = + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "attribute vec4 v_texcoord1;\n" + "varying vec2 source_texture;\n" + "varying vec2 mask_texture;\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n"; + const char *source_coords = " source_texture = v_texcoord0.xy;\n"; + const char *mask_coords = " mask_texture = v_texcoord1.xy;\n"; + const char *main_closing = "}\n"; + const char *source_coords_setup = ""; + const char *mask_coords_setup = ""; + char *source; + GLuint prog; + + if (key->source != SHADER_SOURCE_SOLID) + source_coords_setup = source_coords; + + if (key->mask != SHADER_MASK_NONE && key->mask != SHADER_MASK_SOLID) + mask_coords_setup = mask_coords; + + XNFasprintf(&source, + "%s%s%s%s", + main_opening, + source_coords_setup, mask_coords_setup, main_closing); + + prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, source); + free(source); + + return prog; } static void glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, - glamor_composite_shader * shader) + glamor_composite_shader *shader) { - GLuint vs, fs, prog; - GLint source_sampler_uniform_location, - mask_sampler_uniform_location; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch; - - dispatch = glamor_get_dispatch(glamor_priv); - vs = glamor_create_composite_vs(dispatch, key); - if (vs == 0) - goto out; - fs = glamor_create_composite_fs(dispatch, key); - if (fs == 0) - goto out; - - prog = dispatch->glCreateProgram(); - dispatch->glAttachShader(prog, vs); - dispatch->glAttachShader(prog, fs); - - dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_POS, - "v_position"); - dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, - "v_texcoord0"); - dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, - "v_texcoord1"); - - glamor_link_glsl_prog(dispatch, prog); - - shader->prog = prog; - - dispatch->glUseProgram(prog); - - if (key->source == SHADER_SOURCE_SOLID) { - shader->source_uniform_location = - dispatch->glGetUniformLocation(prog, "source"); - } else { - source_sampler_uniform_location = - dispatch->glGetUniformLocation(prog, "source_sampler"); - dispatch->glUniform1i(source_sampler_uniform_location, 0); - shader->source_wh = dispatch->glGetUniformLocation(prog, "source_wh"); - shader->source_repeat_mode = dispatch->glGetUniformLocation(prog, "source_repeat_mode"); - } - - if (key->mask != SHADER_MASK_NONE) { - if (key->mask == SHADER_MASK_SOLID) { - shader->mask_uniform_location = - dispatch->glGetUniformLocation(prog, "mask"); - } else { - mask_sampler_uniform_location = - dispatch->glGetUniformLocation(prog, - "mask_sampler"); - dispatch->glUniform1i - (mask_sampler_uniform_location, 1); - shader->mask_wh = dispatch->glGetUniformLocation(prog, "mask_wh"); - shader->mask_repeat_mode = dispatch->glGetUniformLocation(prog, "mask_repeat_mode"); - } - } - -out: - glamor_put_dispatch(glamor_priv); + GLuint vs, fs, prog; + GLint source_sampler_uniform_location, mask_sampler_uniform_location; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch; + + dispatch = glamor_get_dispatch(glamor_priv); + vs = glamor_create_composite_vs(dispatch, key); + if (vs == 0) + goto out; + fs = glamor_create_composite_fs(dispatch, key); + if (fs == 0) + goto out; + + prog = dispatch->glCreateProgram(); + dispatch->glAttachShader(prog, vs); + dispatch->glAttachShader(prog, fs); + + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1"); + + glamor_link_glsl_prog(dispatch, prog); + + shader->prog = prog; + + dispatch->glUseProgram(prog); + + if (key->source == SHADER_SOURCE_SOLID) { + shader->source_uniform_location = + dispatch->glGetUniformLocation(prog, "source"); + } + else { + source_sampler_uniform_location = + dispatch->glGetUniformLocation(prog, "source_sampler"); + dispatch->glUniform1i(source_sampler_uniform_location, 0); + shader->source_wh = dispatch->glGetUniformLocation(prog, "source_wh"); + shader->source_repeat_mode = + dispatch->glGetUniformLocation(prog, "source_repeat_mode"); + } + + if (key->mask != SHADER_MASK_NONE) { + if (key->mask == SHADER_MASK_SOLID) { + shader->mask_uniform_location = + dispatch->glGetUniformLocation(prog, "mask"); + } + else { + mask_sampler_uniform_location = + dispatch->glGetUniformLocation(prog, "mask_sampler"); + dispatch->glUniform1i(mask_sampler_uniform_location, 1); + shader->mask_wh = dispatch->glGetUniformLocation(prog, "mask_wh"); + shader->mask_repeat_mode = + dispatch->glGetUniformLocation(prog, "mask_repeat_mode"); + } + } + + out: + glamor_put_dispatch(glamor_priv); } static glamor_composite_shader * glamor_lookup_composite_shader(ScreenPtr screen, struct - shader_key - *key) + shader_key + *key) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_composite_shader *shader; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_composite_shader *shader; - shader = - &glamor_priv->composite_shader[key->source][key-> - mask][key->in]; - if (shader->prog == 0) - glamor_create_composite_shader(screen, key, shader); + shader = &glamor_priv->composite_shader[key->source][key->mask][key->in]; + if (shader->prog == 0) + glamor_create_composite_shader(screen, key, shader); - return shader; + return shader; } static void glamor_init_eb(unsigned short *eb, int vert_cnt) { - int i, j; - for(i = 0, j = 0; j < vert_cnt; i += 6, j += 4) - { - eb[i] = j; - eb[i + 1] = j + 1; - eb[i + 2] = j + 2; - eb[i + 3] = j; - eb[i + 4] = j + 2; - eb[i + 5] = j + 3; - } + int i, j; + + for (i = 0, j = 0; j < vert_cnt; i += 6, j += 4) { + eb[i] = j; + eb[i + 1] = j + 1; + eb[i + 2] = j + 2; + eb[i + 3] = j; + eb[i + 4] = j + 2; + eb[i + 5] = j + 3; + } } void glamor_init_composite_shaders(ScreenPtr screen) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - unsigned short *eb; - float *vb = NULL; - int eb_size; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glGenBuffers(1, &glamor_priv->vbo); - dispatch->glGenBuffers(1, &glamor_priv->ebo); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); - - eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2; - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, - eb_size, - NULL, GL_STATIC_DRAW); - eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - } - else { - vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2); - if (vb == NULL) - FatalError("Failed to allocate vb memory.\n"); - eb = malloc(eb_size); - } - - if (eb == NULL) - FatalError("fatal error, fail to get element buffer. GL context may be not created correctly.\n"); - glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } else { - dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, - eb_size, - eb, GL_STATIC_DRAW); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - dispatch->glBufferData(GL_ARRAY_BUFFER, - GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2, - NULL, GL_DYNAMIC_DRAW); - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - - free(eb); - glamor_priv->vb = (char*)vb; - } - - glamor_put_dispatch(glamor_priv); + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + unsigned short *eb; + float *vb = NULL; + int eb_size; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glGenBuffers(1, &glamor_priv->vbo); + dispatch->glGenBuffers(1, &glamor_priv->ebo); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); + + eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2; + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, + eb_size, NULL, GL_STATIC_DRAW); + eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + } + else { + vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2); + if (vb == NULL) + FatalError("Failed to allocate vb memory.\n"); + eb = malloc(eb_size); + } + + if (eb == NULL) + FatalError + ("fatal error, fail to get element buffer. GL context may be not created correctly.\n"); + glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + else { + dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, + eb_size, eb, GL_STATIC_DRAW); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * + 2, NULL, GL_DYNAMIC_DRAW); + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + + free(eb); + glamor_priv->vb = (char *) vb; + } + + glamor_put_dispatch(glamor_priv); } void glamor_fini_composite_shaders(ScreenPtr screen) { - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - glamor_composite_shader *shader; - int i,j,k; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glDeleteBuffers(1, &glamor_priv->vbo); - dispatch->glDeleteBuffers(1, &glamor_priv->ebo); - - for(i = 0; i < SHADER_SOURCE_COUNT; i++) - for(j = 0; j < SHADER_MASK_COUNT; j++) - for(k = 0; k < SHADER_IN_COUNT; k++) - { - shader = &glamor_priv->composite_shader[i][j][k]; - if (shader->prog) - dispatch->glDeleteProgram(shader->prog); - } - if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP - && glamor_priv->vb) - free(glamor_priv->vb); - - glamor_put_dispatch(glamor_priv); + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + glamor_composite_shader *shader; + int i, j, k; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glDeleteBuffers(1, &glamor_priv->vbo); + dispatch->glDeleteBuffers(1, &glamor_priv->ebo); + + for (i = 0; i < SHADER_SOURCE_COUNT; i++) + for (j = 0; j < SHADER_MASK_COUNT; j++) + for (k = 0; k < SHADER_IN_COUNT; k++) { + shader = &glamor_priv->composite_shader[i][j][k]; + if (shader->prog) + dispatch->glDeleteProgram(shader->prog); + } + if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && glamor_priv->vb) + free(glamor_priv->vb); + + glamor_put_dispatch(glamor_priv); } static Bool glamor_set_composite_op(ScreenPtr screen, - CARD8 op, struct blendinfo *op_info_result, - PicturePtr dest, PicturePtr mask) + CARD8 op, struct blendinfo *op_info_result, + PicturePtr dest, PicturePtr mask) { - GLenum source_blend, dest_blend; - struct blendinfo *op_info; - - if (op >= ARRAY_SIZE(composite_op_info)) { - glamor_fallback("unsupported render op %d \n", op); - return GL_FALSE; - } - op_info = &composite_op_info[op]; - - source_blend = op_info->source_blend; - dest_blend = op_info->dest_blend; - - /* If there's no dst alpha channel, adjust the blend op so that we'll treat - * it as always 1. - */ - if (PICT_FORMAT_A(dest->format) == 0 && op_info->dest_alpha) { - if (source_blend == GL_DST_ALPHA) - source_blend = GL_ONE; - else if (source_blend == GL_ONE_MINUS_DST_ALPHA) - source_blend = GL_ZERO; - } - - /* Set up the source alpha value for blending in component alpha mode. */ - if (mask && mask->componentAlpha - && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) - { - if (dest_blend == GL_SRC_ALPHA) - dest_blend = GL_SRC_COLOR; - else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA) - dest_blend = GL_ONE_MINUS_SRC_COLOR; - } - - op_info_result->source_blend = source_blend; - op_info_result->dest_blend = dest_blend; - op_info_result->source_alpha = op_info->source_alpha; - op_info_result->dest_alpha = op_info->dest_alpha; - - return TRUE; + GLenum source_blend, dest_blend; + struct blendinfo *op_info; + + if (op >= ARRAY_SIZE(composite_op_info)) { + glamor_fallback("unsupported render op %d \n", op); + return GL_FALSE; + } + op_info = &composite_op_info[op]; + + source_blend = op_info->source_blend; + dest_blend = op_info->dest_blend; + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (PICT_FORMAT_A(dest->format) == 0 && op_info->dest_alpha) { + if (source_blend == GL_DST_ALPHA) + source_blend = GL_ONE; + else if (source_blend == GL_ONE_MINUS_DST_ALPHA) + source_blend = GL_ZERO; + } + + /* Set up the source alpha value for blending in component alpha mode. */ + if (mask && mask->componentAlpha + && PICT_FORMAT_RGB(mask->format) != 0 && op_info->source_alpha) { + if (dest_blend == GL_SRC_ALPHA) + dest_blend = GL_SRC_COLOR; + else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA) + dest_blend = GL_ONE_MINUS_SRC_COLOR; + } + + op_info_result->source_blend = source_blend; + op_info_result->dest_blend = dest_blend; + op_info_result->source_alpha = op_info->source_alpha; + op_info_result->dest_alpha = op_info->dest_alpha; + + return TRUE; } static void glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, - PicturePtr picture, - glamor_pixmap_private * pixmap_priv, - GLuint wh_location, GLuint repeat_location) + PicturePtr picture, + glamor_pixmap_private *pixmap_priv, + GLuint wh_location, GLuint repeat_location) { - glamor_gl_dispatch *dispatch; - float wh[4]; - int repeat_type; - - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glActiveTexture(GL_TEXTURE0 + unit); - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex); - repeat_type = picture->repeatType; - switch (picture->repeatType) { - case RepeatNone: + glamor_gl_dispatch *dispatch; + float wh[4]; + int repeat_type; + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glActiveTexture(GL_TEXTURE0 + unit); + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex); + repeat_type = picture->repeatType; + switch (picture->repeatType) { + case RepeatNone: #ifndef GLAMOR_GLES2 - /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */ - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_BORDER); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_BORDER); + /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */ + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_BORDER); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_BORDER); #else - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); #endif - break; - case RepeatNormal: - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_REPEAT); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_REPEAT); - break; - case RepeatPad: - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - break; - case RepeatReflect: - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_MIRRORED_REPEAT); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_MIRRORED_REPEAT); - break; - } - - switch (picture->filter) { - default: - case PictFilterFast: - case PictFilterNearest: - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - break; - case PictFilterGood: - case PictFilterBest: - case PictFilterBilinear: - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_LINEAR); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_LINEAR); - break; - } + break; + case RepeatNormal: + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + break; + case RepeatPad: + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + break; + case RepeatReflect: + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_MIRRORED_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_MIRRORED_REPEAT); + break; + } + + switch (picture->filter) { + default: + case PictFilterFast: + case PictFilterNearest: + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + case PictFilterGood: + case PictFilterBest: + case PictFilterBilinear: + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, GL_LINEAR); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + } #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - /* - * GLES2 doesn't support RepeatNone. We need to fix it anyway. - * - **/ - if (repeat_type != RepeatNone) - repeat_type += RepeatFix; - else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - if (picture->transform - || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) - repeat_type += RepeatFix; - } - if (repeat_type >= RepeatFix) { - glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); - if ((wh[0] != 1.0 || wh[1] != 1.0 ) - || (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && repeat_type == RepeatFix)) - dispatch->glUniform4fv(wh_location, 1, wh); - else - repeat_type -= RepeatFix; - } - dispatch->glUniform1i(repeat_location, repeat_type); - glamor_put_dispatch(glamor_priv); + /* + * GLES2 doesn't support RepeatNone. We need to fix it anyway. + * + **/ + if (repeat_type != RepeatNone) + repeat_type += RepeatFix; + else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (picture->transform + || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) + repeat_type += RepeatFix; + } + if (repeat_type >= RepeatFix) { + glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); + if ((wh[0] != 1.0 || wh[1] != 1.0) + || (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && repeat_type == RepeatFix)) + dispatch->glUniform4fv(wh_location, 1, wh); + else + repeat_type -= RepeatFix; + } + dispatch->glUniform1i(repeat_location, repeat_type); + glamor_put_dispatch(glamor_priv); } static void -glamor_set_composite_solid(glamor_gl_dispatch * dispatch, float *color, - GLint uniform_location) +glamor_set_composite_solid(glamor_gl_dispatch *dispatch, float *color, + GLint uniform_location) { - dispatch->glUniform4fv(uniform_location, 1, color); + dispatch->glUniform4fv(uniform_location, 1, color); } static int compatible_formats(CARD8 op, PicturePtr dst, PicturePtr src) { - if (op == PictOpSrc) { - if (src->format == dst->format) - return 1; - - if (src->format == PICT_a8r8g8b8 - && dst->format == PICT_x8r8g8b8) - return 1; - - if (src->format == PICT_a8b8g8r8 - && dst->format == PICT_x8b8g8r8) - return 1; - } else if (op == PictOpOver) { - if (src->alphaMap || dst->alphaMap) - return 0; - - if (src->format != dst->format) - return 0; - - if (src->format == PICT_x8r8g8b8 - || src->format == PICT_x8b8g8r8) - return 1; - } - - return 0; + if (op == PictOpSrc) { + if (src->format == dst->format) + return 1; + + if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8) + return 1; + + if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8) + return 1; + } + else if (op == PictOpOver) { + if (src->alphaMap || dst->alphaMap) + return 0; + + if (src->format != dst->format) + return 0; + + if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8) + return 1; + } + + return 0; } static char glamor_get_picture_location(PicturePtr picture) { - if (picture == NULL) - return ' '; - - if (picture->pDrawable == NULL) { - switch (picture->pSourcePict->type) { - case SourcePictTypeSolidFill: - return 'c'; - case SourcePictTypeLinear: - return 'l'; - case SourcePictTypeRadial: - return 'r'; - default: - return '?'; - } - } - return glamor_get_drawable_location(picture->pDrawable); + if (picture == NULL) + return ' '; + + if (picture->pDrawable == NULL) { + switch (picture->pSourcePict->type) { + case SourcePictTypeSolidFill: + return 'c'; + case SourcePictTypeLinear: + return 'l'; + case SourcePictTypeRadial: + return 'r'; + default: + return '?'; + } + } + return glamor_get_drawable_location(picture->pDrawable); } static Bool glamor_composite_with_copy(CARD8 op, - PicturePtr source, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_dest, - INT16 y_dest, - RegionPtr region) + PicturePtr source, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_dest, INT16 y_dest, RegionPtr region) { - int ret = FALSE; - if (!source->pDrawable) - return FALSE; - - if (!compatible_formats(op, dest, source)) - return FALSE; - - if (source->repeat || source->transform) { - return FALSE; - } - - x_dest += dest->pDrawable->x; - y_dest += dest->pDrawable->y; - x_source += source->pDrawable->x; - y_source += source->pDrawable->y; - if (PICT_FORMAT_A(source->format) == 0) { - /* Fallback if we sample outside the source so that we - * swizzle the correct clear color for out-of-bounds texels. - */ - if (region->extents.x1 + x_source - x_dest < 0) - goto cleanup_region; - if (region->extents.x2 + x_source - x_dest > source->pDrawable->width) - goto cleanup_region; - - if (region->extents.y1 + y_source - y_dest < 0) - goto cleanup_region; - if (region->extents.y2 + y_source - y_dest > source->pDrawable->height) - goto cleanup_region; - } - ret = glamor_copy_n_to_n_nf(source->pDrawable, - dest->pDrawable, NULL, - RegionRects(region), RegionNumRects(region), - x_source - x_dest, y_source - y_dest, - FALSE, FALSE, 0, NULL); -cleanup_region: - return ret; + int ret = FALSE; + + if (!source->pDrawable) + return FALSE; + + if (!compatible_formats(op, dest, source)) + return FALSE; + + if (source->repeat || source->transform) { + return FALSE; + } + + x_dest += dest->pDrawable->x; + y_dest += dest->pDrawable->y; + x_source += source->pDrawable->x; + y_source += source->pDrawable->y; + if (PICT_FORMAT_A(source->format) == 0) { + /* Fallback if we sample outside the source so that we + * swizzle the correct clear color for out-of-bounds texels. + */ + if (region->extents.x1 + x_source - x_dest < 0) + goto cleanup_region; + if (region->extents.x2 + x_source - x_dest > source->pDrawable->width) + goto cleanup_region; + + if (region->extents.y1 + y_source - y_dest < 0) + goto cleanup_region; + if (region->extents.y2 + y_source - y_dest > source->pDrawable->height) + goto cleanup_region; + } + ret = glamor_copy_n_to_n_nf(source->pDrawable, + dest->pDrawable, NULL, + RegionRects(region), RegionNumRects(region), + x_source - x_dest, y_source - y_dest, + FALSE, FALSE, 0, NULL); + cleanup_region: + return ret; } void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch; - int vert_size; - - glamor_priv->render_nr_verts = 0; - glamor_priv->vb_stride = 2 * sizeof(float); - if (glamor_priv->has_source_coords) - glamor_priv->vb_stride += 2 * sizeof(float); - if (glamor_priv->has_mask_coords) - glamor_priv->vb_stride += 2 * sizeof(float); - - vert_size = n_verts * glamor_priv->vb_stride; - - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) { - glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * - glamor_priv->vb_stride; - glamor_priv->vbo_offset = 0; - dispatch->glBufferData(GL_ARRAY_BUFFER, - glamor_priv->vbo_size, - NULL, GL_STREAM_DRAW); - } - - glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER, - glamor_priv->vbo_offset, - vert_size, - GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); - assert(glamor_priv->vb != NULL); - glamor_priv->vb -= glamor_priv->vbo_offset; - } else - glamor_priv->vbo_offset = 0; - - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) - glamor_priv->vbo_offset)); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - - if (glamor_priv->has_source_coords) { - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, - GL_FLOAT, GL_FALSE, - glamor_priv->vb_stride, - (void *) ((long) - glamor_priv->vbo_offset - + - 2 * - sizeof(float))); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - } - - if (glamor_priv->has_mask_coords) { - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, - GL_FLOAT, GL_FALSE, - glamor_priv->vb_stride, - (void *) ((long) - glamor_priv->vbo_offset - + - (glamor_priv->has_source_coords - ? 4 : 2) * - sizeof(float))); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); - } - glamor_put_dispatch(glamor_priv); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch; + int vert_size; + + glamor_priv->render_nr_verts = 0; + glamor_priv->vb_stride = 2 * sizeof(float); + if (glamor_priv->has_source_coords) + glamor_priv->vb_stride += 2 * sizeof(float); + if (glamor_priv->has_mask_coords) + glamor_priv->vb_stride += 2 * sizeof(float); + + vert_size = n_verts * glamor_priv->vb_stride; + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) { + glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * + glamor_priv->vb_stride; + glamor_priv->vbo_offset = 0; + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_size, NULL, GL_STREAM_DRAW); + } + + glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + vert_size, + GL_MAP_WRITE_BIT | + GL_MAP_UNSYNCHRONIZED_BIT); + assert(glamor_priv->vb != NULL); + glamor_priv->vb -= glamor_priv->vbo_offset; + } + else + glamor_priv->vbo_offset = 0; + + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, glamor_priv->vb_stride, + (void *) ((long) + glamor_priv->vbo_offset)); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + + if (glamor_priv->has_source_coords) { + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, + GL_FLOAT, GL_FALSE, + glamor_priv->vb_stride, (void *) ((long) + glamor_priv-> + vbo_offset + + + 2 * + sizeof + (float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + } + + if (glamor_priv->has_mask_coords) { + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, + GL_FLOAT, GL_FALSE, + glamor_priv->vb_stride, (void *) ((long) + glamor_priv-> + vbo_offset + + + (glamor_priv-> + has_source_coords + ? 4 : + 2) * + sizeof + (float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); + } + glamor_put_dispatch(glamor_priv); } void glamor_emit_composite_vert(ScreenPtr screen, - const float *src_coords, - const float *mask_coords, - const float *dst_coords, int i) + const float *src_coords, + const float *mask_coords, + const float *dst_coords, int i) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - float *vb = (float *) (glamor_priv->vb + glamor_priv->vbo_offset); - int j = 0; - - vb[j++] = dst_coords[i * 2 + 0]; - vb[j++] = dst_coords[i * 2 + 1]; - if (glamor_priv->has_source_coords) { - vb[j++] = src_coords[i * 2 + 0]; - vb[j++] = src_coords[i * 2 + 1]; - } - if (glamor_priv->has_mask_coords) { - vb[j++] = mask_coords[i * 2 + 0]; - vb[j++] = mask_coords[i * 2 + 1]; - } - - glamor_priv->render_nr_verts++; - glamor_priv->vbo_offset += glamor_priv->vb_stride; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + float *vb = (float *) (glamor_priv->vb + glamor_priv->vbo_offset); + int j = 0; + + vb[j++] = dst_coords[i * 2 + 0]; + vb[j++] = dst_coords[i * 2 + 1]; + if (glamor_priv->has_source_coords) { + vb[j++] = src_coords[i * 2 + 0]; + vb[j++] = src_coords[i * 2 + 1]; + } + if (glamor_priv->has_mask_coords) { + vb[j++] = mask_coords[i * 2 + 0]; + vb[j++] = mask_coords[i * 2 + 1]; + } + + glamor_priv->render_nr_verts++; + glamor_priv->vbo_offset += glamor_priv->vb_stride; } - - static void glamor_flush_composite_rects(ScreenPtr screen) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch; - dispatch = glamor_get_dispatch(glamor_priv); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); - else { + dispatch = glamor_get_dispatch(glamor_priv); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + else { - dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - dispatch->glBufferData(GL_ARRAY_BUFFER, - glamor_priv->vbo_offset, - glamor_priv->vb, GL_DYNAMIC_DRAW); - } + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + glamor_priv->vb, GL_DYNAMIC_DRAW); + } - if (!glamor_priv->render_nr_verts) - return; + if (!glamor_priv->render_nr_verts) + return; #ifndef GLAMOR_GLES2 - dispatch->glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts, - (glamor_priv->render_nr_verts * 3) / 2, - GL_UNSIGNED_SHORT, NULL); + dispatch->glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts, + (glamor_priv->render_nr_verts * 3) / 2, + GL_UNSIGNED_SHORT, NULL); #else - dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, - GL_UNSIGNED_SHORT, NULL); + dispatch->glDrawElements(GL_TRIANGLES, + (glamor_priv->render_nr_verts * 3) / 2, + GL_UNSIGNED_SHORT, NULL); #endif - glamor_put_dispatch(glamor_priv); + glamor_put_dispatch(glamor_priv); } int pict_format_combine_tab[][3] = { - {PICT_TYPE_ARGB, PICT_TYPE_A, PICT_TYPE_ARGB}, - {PICT_TYPE_ABGR, PICT_TYPE_A, PICT_TYPE_ABGR}, + {PICT_TYPE_ARGB, PICT_TYPE_A, PICT_TYPE_ARGB}, + {PICT_TYPE_ABGR, PICT_TYPE_A, PICT_TYPE_ABGR}, }; static Bool combine_pict_format(PictFormatShort * des, const PictFormatShort src, - const PictFormatShort mask, enum shader_in in_ca) + const PictFormatShort mask, enum shader_in in_ca) { - PictFormatShort new_vis; - int src_type, mask_type, src_bpp, mask_bpp; - int i; - if (src == mask) { - *des = src; - return TRUE; - } - src_bpp = PICT_FORMAT_BPP(src); - mask_bpp = PICT_FORMAT_BPP(mask); - - assert(src_bpp == mask_bpp); - - new_vis = PICT_FORMAT_VIS(src) | PICT_FORMAT_VIS(mask); - - switch (in_ca) { - case SHADER_IN_SOURCE_ONLY: - return TRUE; - case SHADER_IN_NORMAL: - src_type = PICT_FORMAT_TYPE(src); - mask_type = PICT_TYPE_A; - break; - case SHADER_IN_CA_SOURCE: - src_type = PICT_FORMAT_TYPE(src); - mask_type = PICT_FORMAT_TYPE(mask); - break; - case SHADER_IN_CA_ALPHA: - src_type = PICT_TYPE_A; - mask_type = PICT_FORMAT_TYPE(mask); - break; - default: - return FALSE; - } - - if (src_type == mask_type) { - *des = PICT_VISFORMAT(src_bpp, src_type, new_vis); - return TRUE; - } - - for (i = 0; - i < - sizeof(pict_format_combine_tab) / - sizeof(pict_format_combine_tab[0]); i++) { - if ((src_type == pict_format_combine_tab[i][0] - && mask_type == pict_format_combine_tab[i][1]) - || (src_type == pict_format_combine_tab[i][1] - && mask_type == pict_format_combine_tab[i][0])) { - *des = PICT_VISFORMAT(src_bpp, - pict_format_combine_tab[i] - [2], new_vis); - return TRUE; - } - } - return FALSE; + PictFormatShort new_vis; + int src_type, mask_type, src_bpp; + int i; + + if (src == mask) { + *des = src; + return TRUE; + } + src_bpp = PICT_FORMAT_BPP(src); + + assert(src_bpp == PICT_FORMAT_BPP(mask)); + + new_vis = PICT_FORMAT_VIS(src) | PICT_FORMAT_VIS(mask); + + switch (in_ca) { + case SHADER_IN_SOURCE_ONLY: + return TRUE; + case SHADER_IN_NORMAL: + src_type = PICT_FORMAT_TYPE(src); + mask_type = PICT_TYPE_A; + break; + case SHADER_IN_CA_SOURCE: + src_type = PICT_FORMAT_TYPE(src); + mask_type = PICT_FORMAT_TYPE(mask); + break; + case SHADER_IN_CA_ALPHA: + src_type = PICT_TYPE_A; + mask_type = PICT_FORMAT_TYPE(mask); + break; + default: + return FALSE; + } + + if (src_type == mask_type) { + *des = PICT_VISFORMAT(src_bpp, src_type, new_vis); + return TRUE; + } + + for (i = 0; + i < + sizeof(pict_format_combine_tab) / + sizeof(pict_format_combine_tab[0]); i++) { + if ((src_type == pict_format_combine_tab[i][0] + && mask_type == pict_format_combine_tab[i][1]) + || (src_type == pict_format_combine_tab[i][1] + && mask_type == pict_format_combine_tab[i][0])) { + *des = PICT_VISFORMAT(src_bpp, pict_format_combine_tab[i] + [2], new_vis); + return TRUE; + } + } + return FALSE; } static void glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, - int repeat_type, - float *matrix, - float xscale, float yscale, - int x1, int y1, int x2, int y2, - int yInverted, float *texcoords, - int stride) + int repeat_type, + float *matrix, + float xscale, float yscale, + int x1, int y1, int x2, int y2, + int yInverted, float *texcoords, + int stride) { - if (!matrix && repeat_type == RepeatNone) - glamor_set_normalize_tcoords_ext(priv, xscale, yscale, - x1, y1, - x2, y2, - yInverted, - texcoords, stride); - else if (matrix && repeat_type == RepeatNone) - glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, - yscale, x1, y1, - x2, y2, - yInverted, - texcoords, stride); - else if (!matrix && repeat_type != RepeatNone) - glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, - xscale, yscale, - x1, y1, - x2, y2, - yInverted, - texcoords, stride); - else if (matrix && repeat_type != RepeatNone) - glamor_set_repeat_transformed_normalize_tcoords_ext(priv, repeat_type, - matrix, xscale, yscale, - x1, y1, - x2, y2, - yInverted, - texcoords, stride); + if (!matrix && repeat_type == RepeatNone) + glamor_set_normalize_tcoords_ext(priv, xscale, yscale, + x1, y1, + x2, y2, yInverted, texcoords, stride); + else if (matrix && repeat_type == RepeatNone) + glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, + yscale, x1, y1, + x2, y2, + yInverted, + texcoords, stride); + else if (!matrix && repeat_type != RepeatNone) + glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, + xscale, yscale, + x1, y1, + x2, y2, + yInverted, texcoords, stride); + else if (matrix && repeat_type != RepeatNone) + glamor_set_repeat_transformed_normalize_tcoords_ext(priv, repeat_type, + matrix, xscale, + yscale, x1, y1, x2, + y2, yInverted, + texcoords, stride); } -Bool glamor_composite_choose_shader(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, - struct shader_key *s_key, - glamor_composite_shader **shader, - struct blendinfo *op_info, - PictFormatShort *psaved_source_format) +Bool +glamor_composite_choose_shader(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, + struct shader_key *s_key, + glamor_composite_shader ** shader, + struct blendinfo *op_info, + PictFormatShort *psaved_source_format) { - ScreenPtr screen = dest->pDrawable->pScreen; - PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; - PixmapPtr source_pixmap = NULL; - PixmapPtr mask_pixmap = NULL; - enum glamor_pixmap_status source_status = GLAMOR_NONE; - enum glamor_pixmap_status mask_status = GLAMOR_NONE; - PictFormatShort saved_source_format = 0; - struct shader_key key; - GLfloat source_solid_color[4]; - GLfloat mask_solid_color[4]; - Bool ret = FALSE; - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - glamor_fallback("dest has no fbo.\n"); - goto fail; - } - - memset(&key, 0, sizeof(key)); - if (!source) { - key.source = SHADER_SOURCE_SOLID; - source_solid_color[0] = 0.0; - source_solid_color[1] = 0.0; - source_solid_color[2] = 0.0; - source_solid_color[3] = 0.0; - } else if (!source->pDrawable) { - if (source->pSourcePict->type == SourcePictTypeSolidFill) { - key.source = SHADER_SOURCE_SOLID; - glamor_get_rgba_from_pixel(source-> - pSourcePict->solidFill. - color, - &source_solid_color[0], - &source_solid_color[1], - &source_solid_color[2], - &source_solid_color[3], - PICT_a8r8g8b8); - } else - goto fail; - } else { - key.source = SHADER_SOURCE_TEXTURE_ALPHA; - } - - if (mask) { - if (!mask->pDrawable) { - if (mask->pSourcePict->type == - SourcePictTypeSolidFill) { - key.mask = SHADER_MASK_SOLID; - glamor_get_rgba_from_pixel - (mask->pSourcePict->solidFill.color, - &mask_solid_color[0], - &mask_solid_color[1], - &mask_solid_color[2], - &mask_solid_color[3], PICT_a8r8g8b8); - } else - goto fail; - } else { - key.mask = SHADER_MASK_TEXTURE_ALPHA; - } - - if (!mask->componentAlpha) { - key.in = SHADER_IN_NORMAL; - } else { - if (op == PictOpClear) - key.mask = SHADER_MASK_NONE; - else if (op == PictOpSrc || op == PictOpAdd - || op == PictOpIn || op == PictOpOut - || op == PictOpOverReverse) - key.in = SHADER_IN_CA_SOURCE; - else if (op == PictOpOutReverse || op == PictOpInReverse) { - key.in = SHADER_IN_CA_ALPHA; - } else { - glamor_fallback("Unsupported component alpha op: %d\n", op); - goto fail; - } - } - } else { - key.mask = SHADER_MASK_NONE; - key.in = SHADER_IN_SOURCE_ONLY; - } - - if (source && source->alphaMap) { - glamor_fallback("source alphaMap\n"); - goto fail; - } - if (mask && mask->alphaMap) { - glamor_fallback("mask alphaMap\n"); - goto fail; - } - - if (key.source == SHADER_SOURCE_TEXTURE || - key.source == SHADER_SOURCE_TEXTURE_ALPHA) { - source_pixmap = source_pixmap_priv->base.pixmap; - if (source_pixmap == dest_pixmap) { - /* XXX source and the dest share the same texture. - * Does it need special handle? */ - glamor_fallback("source == dest\n"); - } - if (source_pixmap_priv->base.gl_fbo == 0) { - /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex - * equal to zero when the pixmap is screen pixmap. Then we may - * refer the tex zero directly latter in the composition. - * It seems that it works fine, but it may have potential problem*/ + ScreenPtr screen = dest->pDrawable->pScreen; + PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; + PixmapPtr source_pixmap = NULL; + PixmapPtr mask_pixmap = NULL; + enum glamor_pixmap_status source_status = GLAMOR_NONE; + enum glamor_pixmap_status mask_status = GLAMOR_NONE; + PictFormatShort saved_source_format = 0; + struct shader_key key; + GLfloat source_solid_color[4]; + GLfloat mask_solid_color[4]; + Bool ret = FALSE; + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + glamor_fallback("dest has no fbo.\n"); + goto fail; + } + + memset(&key, 0, sizeof(key)); + if (!source) { + key.source = SHADER_SOURCE_SOLID; + source_solid_color[0] = 0.0; + source_solid_color[1] = 0.0; + source_solid_color[2] = 0.0; + source_solid_color[3] = 0.0; + } + else if (!source->pDrawable) { + if (source->pSourcePict->type == SourcePictTypeSolidFill) { + key.source = SHADER_SOURCE_SOLID; + glamor_get_rgba_from_pixel(source->pSourcePict->solidFill.color, + &source_solid_color[0], + &source_solid_color[1], + &source_solid_color[2], + &source_solid_color[3], PICT_a8r8g8b8); + } + else + goto fail; + } + else { + key.source = SHADER_SOURCE_TEXTURE_ALPHA; + } + + if (mask) { + if (!mask->pDrawable) { + if (mask->pSourcePict->type == SourcePictTypeSolidFill) { + key.mask = SHADER_MASK_SOLID; + glamor_get_rgba_from_pixel + (mask->pSourcePict->solidFill.color, + &mask_solid_color[0], + &mask_solid_color[1], + &mask_solid_color[2], &mask_solid_color[3], PICT_a8r8g8b8); + } + else + goto fail; + } + else { + key.mask = SHADER_MASK_TEXTURE_ALPHA; + } + + if (!mask->componentAlpha) { + key.in = SHADER_IN_NORMAL; + } + else { + if (op == PictOpClear) + key.mask = SHADER_MASK_NONE; + else if (op == PictOpSrc || op == PictOpAdd + || op == PictOpIn || op == PictOpOut + || op == PictOpOverReverse) + key.in = SHADER_IN_CA_SOURCE; + else if (op == PictOpOutReverse || op == PictOpInReverse) { + key.in = SHADER_IN_CA_ALPHA; + } + else { + glamor_fallback("Unsupported component alpha op: %d\n", op); + goto fail; + } + } + } + else { + key.mask = SHADER_MASK_NONE; + key.in = SHADER_IN_SOURCE_ONLY; + } + + if (source && source->alphaMap) { + glamor_fallback("source alphaMap\n"); + goto fail; + } + if (mask && mask->alphaMap) { + glamor_fallback("mask alphaMap\n"); + goto fail; + } + + if (key.source == SHADER_SOURCE_TEXTURE || + key.source == SHADER_SOURCE_TEXTURE_ALPHA) { + source_pixmap = source_pixmap_priv->base.pixmap; + if (source_pixmap == dest_pixmap) { + /* XXX source and the dest share the same texture. + * Does it need special handle? */ + glamor_fallback("source == dest\n"); + } + if (source_pixmap_priv->base.gl_fbo == 0) { + /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex + * equal to zero when the pixmap is screen pixmap. Then we may + * refer the tex zero directly latter in the composition. + * It seems that it works fine, but it may have potential problem*/ #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - source_status = GLAMOR_UPLOAD_PENDING; + source_status = GLAMOR_UPLOAD_PENDING; #else - glamor_fallback("no texture in source\n"); - goto fail; + glamor_fallback("no texture in source\n"); + goto fail; #endif - } - } - - if (key.mask == SHADER_MASK_TEXTURE || - key.mask == SHADER_MASK_TEXTURE_ALPHA) { - mask_pixmap = mask_pixmap_priv->base.pixmap; - if (mask_pixmap == dest_pixmap) { - glamor_fallback("mask == dest\n"); - goto fail; - } - if (mask_pixmap_priv->base.gl_fbo == 0) { + } + } + + if (key.mask == SHADER_MASK_TEXTURE || + key.mask == SHADER_MASK_TEXTURE_ALPHA) { + mask_pixmap = mask_pixmap_priv->base.pixmap; + if (mask_pixmap == dest_pixmap) { + glamor_fallback("mask == dest\n"); + goto fail; + } + if (mask_pixmap_priv->base.gl_fbo == 0) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - mask_status = GLAMOR_UPLOAD_PENDING; + mask_status = GLAMOR_UPLOAD_PENDING; #else - glamor_fallback("no texture in mask\n"); - goto fail; + glamor_fallback("no texture in mask\n"); + goto fail; #endif - } - } + } + } #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - if (source_status == GLAMOR_UPLOAD_PENDING - && mask_status == GLAMOR_UPLOAD_PENDING - && source_pixmap == mask_pixmap) { - - if (source->format != mask->format) { - saved_source_format = source->format; - - if (!combine_pict_format(&source->format, source->format, - mask->format, key.in)) { - glamor_fallback("combine source %x mask %x failed.\n", - source->format, mask->format); - goto fail; - } - - if (source->format != saved_source_format) { - glamor_picture_format_fixup(source, - source_pixmap_priv); - } - /* XXX - * By default, glamor_upload_picture_to_texture will wire alpha to 1 - * if one picture doesn't have alpha. So we don't do that again in - * rendering function. But here is a special case, as source and - * mask share the same texture but may have different formats. For - * example, source doesn't have alpha, but mask has alpha. Then the - * texture will have the alpha value for the mask. And will not wire - * to 1 for the source. In this case, we have to use different shader - * to wire the source's alpha to 1. - * - * But this may cause a potential problem if the source's repeat mode - * is REPEAT_NONE, and if the source is smaller than the dest, then - * for the region not covered by the source may be painted incorrectly. - * because we wire the alpha to 1. - * - **/ - if (!PICT_FORMAT_A(saved_source_format) - && PICT_FORMAT_A(mask->format)) - key.source = SHADER_SOURCE_TEXTURE; - - if (!PICT_FORMAT_A(mask->format) - && PICT_FORMAT_A(saved_source_format)) - key.mask = SHADER_MASK_TEXTURE; - - mask_status = GLAMOR_NONE; - } - - source_status = glamor_upload_picture_to_texture(source); - if (source_status != GLAMOR_UPLOAD_DONE) { - glamor_fallback("Failed to upload source texture.\n"); - goto fail; - } - } else { - if (source_status == GLAMOR_UPLOAD_PENDING) { - source_status = glamor_upload_picture_to_texture(source); - if (source_status != GLAMOR_UPLOAD_DONE) { - glamor_fallback("Failed to upload source texture.\n"); - goto fail; - } - } - - if (mask_status == GLAMOR_UPLOAD_PENDING) { - mask_status = glamor_upload_picture_to_texture(mask); - if (mask_status != GLAMOR_UPLOAD_DONE) { - glamor_fallback("Failed to upload mask texture.\n"); - goto fail; - } - } - } + if (source_status == GLAMOR_UPLOAD_PENDING + && mask_status == GLAMOR_UPLOAD_PENDING + && source_pixmap == mask_pixmap) { + + if (source->format != mask->format) { + saved_source_format = source->format; + + if (!combine_pict_format(&source->format, source->format, + mask->format, key.in)) { + glamor_fallback("combine source %x mask %x failed.\n", + source->format, mask->format); + goto fail; + } + + if (source->format != saved_source_format) { + glamor_picture_format_fixup(source, source_pixmap_priv); + } + /* XXX + * By default, glamor_upload_picture_to_texture will wire alpha to 1 + * if one picture doesn't have alpha. So we don't do that again in + * rendering function. But here is a special case, as source and + * mask share the same texture but may have different formats. For + * example, source doesn't have alpha, but mask has alpha. Then the + * texture will have the alpha value for the mask. And will not wire + * to 1 for the source. In this case, we have to use different shader + * to wire the source's alpha to 1. + * + * But this may cause a potential problem if the source's repeat mode + * is REPEAT_NONE, and if the source is smaller than the dest, then + * for the region not covered by the source may be painted incorrectly. + * because we wire the alpha to 1. + * + **/ + if (!PICT_FORMAT_A(saved_source_format) + && PICT_FORMAT_A(mask->format)) + key.source = SHADER_SOURCE_TEXTURE; + + if (!PICT_FORMAT_A(mask->format) + && PICT_FORMAT_A(saved_source_format)) + key.mask = SHADER_MASK_TEXTURE; + + mask_status = GLAMOR_NONE; + } + + source_status = glamor_upload_picture_to_texture(source); + if (source_status != GLAMOR_UPLOAD_DONE) { + glamor_fallback("Failed to upload source texture.\n"); + goto fail; + } + } + else { + if (source_status == GLAMOR_UPLOAD_PENDING) { + source_status = glamor_upload_picture_to_texture(source); + if (source_status != GLAMOR_UPLOAD_DONE) { + glamor_fallback("Failed to upload source texture.\n"); + goto fail; + } + } + + if (mask_status == GLAMOR_UPLOAD_PENDING) { + mask_status = glamor_upload_picture_to_texture(mask); + if (mask_status != GLAMOR_UPLOAD_DONE) { + glamor_fallback("Failed to upload mask texture.\n"); + goto fail; + } + } + } #endif - /*Before enter the rendering stage, we need to fixup - * transformed source and mask, if the transform is not int translate. */ - if (key.source != SHADER_SOURCE_SOLID - && source->transform - && !pixman_transform_is_int_translate(source->transform) - && source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { - if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv)) - goto fail; - } - if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID - && mask->transform - && !pixman_transform_is_int_translate(mask->transform) - && mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { - if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv)) - goto fail; - } - - - if (!glamor_set_composite_op(screen, op, op_info, dest, mask)) - goto fail; - - *shader = glamor_lookup_composite_shader(screen, &key); - if ((*shader)->prog == 0) { - glamor_fallback("no shader program for this" - "render acccel mode\n"); - goto fail; - } - - if (key.source == SHADER_SOURCE_SOLID) - memcpy(&(*shader)->source_solid_color[0], - source_solid_color, 4*sizeof(float)); - else { - (*shader)->source_priv = source_pixmap_priv; - (*shader)->source = source; - } - - if (key.mask == SHADER_MASK_SOLID) - memcpy(&(*shader)->mask_solid_color[0], - mask_solid_color, 4*sizeof(float)); - else { - (*shader)->mask_priv = mask_pixmap_priv; - (*shader)->mask = mask; - } - - ret = TRUE; - memcpy(s_key, &key, sizeof(key)); - *psaved_source_format = saved_source_format; - goto done; - -fail: - if (saved_source_format) - source->format = saved_source_format; -done: - return ret; + /*Before enter the rendering stage, we need to fixup + * transformed source and mask, if the transform is not int translate. */ + if (key.source != SHADER_SOURCE_SOLID + && source->transform + && !pixman_transform_is_int_translate(source->transform) + && source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv)) + goto fail; + } + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID + && mask->transform + && !pixman_transform_is_int_translate(mask->transform) + && mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv)) + goto fail; + } + + if (!glamor_set_composite_op(screen, op, op_info, dest, mask)) + goto fail; + + *shader = glamor_lookup_composite_shader(screen, &key); + if ((*shader)->prog == 0) { + glamor_fallback("no shader program for this render acccel mode\n"); + goto fail; + } + + if (key.source == SHADER_SOURCE_SOLID) + memcpy(&(*shader)->source_solid_color[0], + source_solid_color, 4 * sizeof(float)); + else { + (*shader)->source_priv = source_pixmap_priv; + (*shader)->source = source; + } + + if (key.mask == SHADER_MASK_SOLID) + memcpy(&(*shader)->mask_solid_color[0], + mask_solid_color, 4 * sizeof(float)); + else { + (*shader)->mask_priv = mask_pixmap_priv; + (*shader)->mask = mask; + } + + ret = TRUE; + memcpy(s_key, &key, sizeof(key)); + *psaved_source_format = saved_source_format; + goto done; + + fail: + if (saved_source_format) + source->format = saved_source_format; + done: + return ret; } void glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, - struct shader_key *key, - glamor_composite_shader *shader, - struct blendinfo *op_info) + struct shader_key *key, + glamor_composite_shader *shader, + struct blendinfo *op_info) { - glamor_gl_dispatch *dispatch; - glamor_screen_private *glamor_priv; - - glamor_priv = dest_priv->base.glamor_priv; - - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glUseProgram(shader->prog); - - if (key->source == SHADER_SOURCE_SOLID) { - glamor_set_composite_solid(dispatch, - shader->source_solid_color, - shader->source_uniform_location); - } else { - glamor_set_composite_texture(glamor_priv, 0, - shader->source, - shader->source_priv, shader->source_wh, - shader->source_repeat_mode); - } - - if (key->mask != SHADER_MASK_NONE) { - if (key->mask == SHADER_MASK_SOLID) { - glamor_set_composite_solid(dispatch, - shader->mask_solid_color, - shader->mask_uniform_location); - } else { - glamor_set_composite_texture(glamor_priv, 1, - shader->mask, - shader->mask_priv, shader->mask_wh, - shader->mask_repeat_mode); - } - } - - if (op_info->source_blend == GL_ONE - && op_info->dest_blend == GL_ZERO) { - dispatch->glDisable(GL_BLEND); - } else { - dispatch->glEnable(GL_BLEND); - dispatch->glBlendFunc(op_info->source_blend, - op_info->dest_blend); - } - - glamor_put_dispatch(glamor_priv); + glamor_gl_dispatch *dispatch; + glamor_screen_private *glamor_priv; + + glamor_priv = dest_priv->base.glamor_priv; + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glUseProgram(shader->prog); + + if (key->source == SHADER_SOURCE_SOLID) { + glamor_set_composite_solid(dispatch, + shader->source_solid_color, + shader->source_uniform_location); + } + else { + glamor_set_composite_texture(glamor_priv, 0, + shader->source, + shader->source_priv, shader->source_wh, + shader->source_repeat_mode); + } + + if (key->mask != SHADER_MASK_NONE) { + if (key->mask == SHADER_MASK_SOLID) { + glamor_set_composite_solid(dispatch, + shader->mask_solid_color, + shader->mask_uniform_location); + } + else { + glamor_set_composite_texture(glamor_priv, 1, + shader->mask, + shader->mask_priv, shader->mask_wh, + shader->mask_repeat_mode); + } + } + + if (op_info->source_blend == GL_ONE && op_info->dest_blend == GL_ZERO) { + dispatch->glDisable(GL_BLEND); + } + else { + dispatch->glEnable(GL_BLEND); + dispatch->glBlendFunc(op_info->source_blend, op_info->dest_blend); + } + + glamor_put_dispatch(glamor_priv); } static Bool glamor_composite_with_shader(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, - int nrect, glamor_composite_rect_t * rects, - Bool two_pass_ca) + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, + int nrect, glamor_composite_rect_t *rects, + Bool two_pass_ca) { - ScreenPtr screen = dest->pDrawable->pScreen; - glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; - PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; - PixmapPtr source_pixmap = NULL; - PixmapPtr mask_pixmap = NULL; - glamor_gl_dispatch *dispatch = NULL; - GLfloat dst_xscale, dst_yscale; - GLfloat mask_xscale = 1, mask_yscale = 1, - src_xscale = 1, src_yscale = 1; - struct shader_key key, key_ca; - float *vertices; - int dest_x_off, dest_y_off; - int source_x_off, source_y_off; - int mask_x_off, mask_y_off; - PictFormatShort saved_source_format = 0; - float src_matrix[9], mask_matrix[9]; - float *psrc_matrix = NULL, *pmask_matrix = NULL; - int vert_stride = 4; - int nrect_max; - Bool ret = FALSE; - glamor_composite_shader *shader = NULL, *shader_ca = NULL; - struct blendinfo op_info, op_info_ca; - - if(!glamor_composite_choose_shader(op, source, mask, dest, - source_pixmap_priv, mask_pixmap_priv, - dest_pixmap_priv, - &key, &shader, &op_info, - &saved_source_format)) { - glamor_fallback("glamor_composite_choose_shader failed\n"); - return ret; - } - if (two_pass_ca) { - if(!glamor_composite_choose_shader(PictOpAdd, source, mask, dest, - source_pixmap_priv, mask_pixmap_priv, - dest_pixmap_priv, - &key_ca, &shader_ca, &op_info_ca, - &saved_source_format)) { - glamor_fallback("glamor_composite_choose_shader failed\n"); - return ret; - } - } - - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); - glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info); - - dispatch = glamor_get_dispatch(glamor_priv); - - glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID; - glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE && - key.mask != SHADER_MASK_SOLID); - - dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, - &dest_x_off, &dest_y_off); - pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); - - if (glamor_priv->has_source_coords) { - source_pixmap = source_pixmap_priv->base.pixmap; - glamor_get_drawable_deltas(source->pDrawable, - source_pixmap, &source_x_off, - &source_y_off); - pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, - &src_yscale); - if (source->transform) { - psrc_matrix = src_matrix; - glamor_picture_get_matrixf(source, psrc_matrix); - } - vert_stride += 4; - } - - if (glamor_priv->has_mask_coords) { - mask_pixmap = mask_pixmap_priv->base.pixmap; - glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, - &mask_x_off, &mask_y_off); - pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, - &mask_yscale); - if (mask->transform) { - pmask_matrix = mask_matrix; - glamor_picture_get_matrixf(mask, pmask_matrix); - } - vert_stride += 4; - } - - nrect_max = (vert_stride * nrect) > GLAMOR_COMPOSITE_VBO_VERT_CNT ? - (GLAMOR_COMPOSITE_VBO_VERT_CNT / vert_stride) : nrect; - - while(nrect) { - int mrect, rect_processed; - int vb_stride; - - mrect = nrect > nrect_max ? nrect_max : nrect ; - glamor_setup_composite_vbo(screen, mrect * vert_stride); - rect_processed = mrect; - vb_stride = glamor_priv->vb_stride/sizeof(float); - while (mrect--) { - INT16 x_source; - INT16 y_source; - INT16 x_mask; - INT16 y_mask; - INT16 x_dest; - INT16 y_dest; - CARD16 width; - CARD16 height; - - x_dest = rects->x_dst + dest_x_off; - y_dest = rects->y_dst + dest_y_off; - x_source = rects->x_src + source_x_off; - y_source = rects->y_src + source_y_off; - x_mask = rects->x_mask + mask_x_off; - y_mask = rects->y_mask + mask_y_off; - width = rects->width; - height = rects->height; - - DEBUGF("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n", - x_dest, y_dest, x_source, y_source,x_mask,y_mask,width,height); - vertices = (float*)(glamor_priv->vb + glamor_priv->vbo_offset); - assert(glamor_priv->vbo_offset < glamor_priv->vbo_size - glamor_priv->vb_stride); - glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale, - dst_yscale, - x_dest, y_dest, - x_dest + width, y_dest + height, - glamor_priv->yInverted, - vertices, vb_stride); - vertices += 2; - if (key.source != SHADER_SOURCE_SOLID) { - glamor_set_normalize_tcoords_generic( - source_pixmap_priv, source->repeatType, psrc_matrix, - src_xscale, src_yscale, x_source, y_source, - x_source + width, y_source + height, - glamor_priv->yInverted, vertices, vb_stride); - vertices += 2; - } - - if (key.mask != SHADER_MASK_NONE - && key.mask != SHADER_MASK_SOLID) { - glamor_set_normalize_tcoords_generic( - mask_pixmap_priv, mask->repeatType, pmask_matrix, - mask_xscale, mask_yscale, x_mask, y_mask, - x_mask + width, y_mask + height, - glamor_priv->yInverted, vertices, vb_stride); - } - glamor_priv->render_nr_verts += 4; - glamor_priv->vbo_offset += glamor_priv->vb_stride * 4; - rects++; - } - glamor_flush_composite_rects(screen); - nrect -= rect_processed; - if (two_pass_ca) { - glamor_composite_set_shader_blend(dest_pixmap_priv, - &key_ca, shader_ca, - &op_info_ca); - glamor_flush_composite_rects(screen); - if (nrect) - glamor_composite_set_shader_blend(dest_pixmap_priv, - &key, shader, - &op_info); - } - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); - dispatch->glDisable(GL_BLEND); + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; + PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; + PixmapPtr source_pixmap = NULL; + PixmapPtr mask_pixmap = NULL; + glamor_gl_dispatch *dispatch = NULL; + GLfloat dst_xscale, dst_yscale; + GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; + struct shader_key key, key_ca; + float *vertices; + int dest_x_off, dest_y_off; + int source_x_off, source_y_off; + int mask_x_off, mask_y_off; + PictFormatShort saved_source_format = 0; + float src_matrix[9], mask_matrix[9]; + float *psrc_matrix = NULL, *pmask_matrix = NULL; + int vert_stride = 4; + int nrect_max; + Bool ret = FALSE; + glamor_composite_shader *shader = NULL, *shader_ca = NULL; + struct blendinfo op_info, op_info_ca; + + if (!glamor_composite_choose_shader(op, source, mask, dest, + source_pixmap_priv, mask_pixmap_priv, + dest_pixmap_priv, + &key, &shader, &op_info, + &saved_source_format)) { + glamor_fallback("glamor_composite_choose_shader failed\n"); + return ret; + } + if (two_pass_ca) { + if (!glamor_composite_choose_shader(PictOpAdd, source, mask, dest, + source_pixmap_priv, + mask_pixmap_priv, dest_pixmap_priv, + &key_ca, &shader_ca, &op_info_ca, + &saved_source_format)) { + glamor_fallback("glamor_composite_choose_shader failed\n"); + return ret; + } + } + + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); + glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info); + + dispatch = glamor_get_dispatch(glamor_priv); + + glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID; + glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE && + key.mask != SHADER_MASK_SOLID); + + dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, + &dest_x_off, &dest_y_off); + pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); + + if (glamor_priv->has_source_coords) { + source_pixmap = source_pixmap_priv->base.pixmap; + glamor_get_drawable_deltas(source->pDrawable, + source_pixmap, &source_x_off, &source_y_off); + pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); + if (source->transform) { + psrc_matrix = src_matrix; + glamor_picture_get_matrixf(source, psrc_matrix); + } + vert_stride += 4; + } + + if (glamor_priv->has_mask_coords) { + mask_pixmap = mask_pixmap_priv->base.pixmap; + glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, + &mask_x_off, &mask_y_off); + pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); + if (mask->transform) { + pmask_matrix = mask_matrix; + glamor_picture_get_matrixf(mask, pmask_matrix); + } + vert_stride += 4; + } + + nrect_max = (vert_stride * nrect) > GLAMOR_COMPOSITE_VBO_VERT_CNT ? + (GLAMOR_COMPOSITE_VBO_VERT_CNT / vert_stride) : nrect; + + while (nrect) { + int mrect, rect_processed; + int vb_stride; + + mrect = nrect > nrect_max ? nrect_max : nrect; + glamor_setup_composite_vbo(screen, mrect * vert_stride); + rect_processed = mrect; + vb_stride = glamor_priv->vb_stride / sizeof(float); + while (mrect--) { + INT16 x_source; + INT16 y_source; + INT16 x_mask; + INT16 y_mask; + INT16 x_dest; + INT16 y_dest; + CARD16 width; + CARD16 height; + + x_dest = rects->x_dst + dest_x_off; + y_dest = rects->y_dst + dest_y_off; + x_source = rects->x_src + source_x_off; + y_source = rects->y_src + source_y_off; + x_mask = rects->x_mask + mask_x_off; + y_mask = rects->y_mask + mask_y_off; + width = rects->width; + height = rects->height; + + DEBUGF + ("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n", + x_dest, y_dest, x_source, y_source, x_mask, y_mask, width, + height); + vertices = (float *) (glamor_priv->vb + glamor_priv->vbo_offset); + assert(glamor_priv->vbo_offset < + glamor_priv->vbo_size - glamor_priv->vb_stride); + glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale, + dst_yscale, x_dest, y_dest, + x_dest + width, y_dest + height, + glamor_priv->yInverted, vertices, + vb_stride); + vertices += 2; + if (key.source != SHADER_SOURCE_SOLID) { + glamor_set_normalize_tcoords_generic(source_pixmap_priv, + source->repeatType, + psrc_matrix, src_xscale, + src_yscale, x_source, + y_source, x_source + width, + y_source + height, + glamor_priv->yInverted, + vertices, vb_stride); + vertices += 2; + } + + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { + glamor_set_normalize_tcoords_generic(mask_pixmap_priv, + mask->repeatType, + pmask_matrix, mask_xscale, + mask_yscale, x_mask, + y_mask, x_mask + width, + y_mask + height, + glamor_priv->yInverted, + vertices, vb_stride); + } + glamor_priv->render_nr_verts += 4; + glamor_priv->vbo_offset += glamor_priv->vb_stride * 4; + rects++; + } + glamor_flush_composite_rects(screen); + nrect -= rect_processed; + if (two_pass_ca) { + glamor_composite_set_shader_blend(dest_pixmap_priv, + &key_ca, shader_ca, &op_info_ca); + glamor_flush_composite_rects(screen); + if (nrect) + glamor_composite_set_shader_blend(dest_pixmap_priv, + &key, shader, &op_info); + } + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); + dispatch->glDisable(GL_BLEND); #ifndef GLAMOR_GLES2 - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glDisable(GL_TEXTURE_2D); - dispatch->glActiveTexture(GL_TEXTURE1); - dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glActiveTexture(GL_TEXTURE1); + dispatch->glDisable(GL_TEXTURE_2D); #endif - DEBUGF("finish rendering.\n"); - dispatch->glUseProgram(0); - glamor_priv->state = RENDER_STATE; - glamor_priv->render_idle_cnt = 0; - if (saved_source_format) - source->format = saved_source_format; - glamor_put_dispatch(glamor_priv); - - ret = TRUE; - return ret; + DEBUGF("finish rendering.\n"); + dispatch->glUseProgram(0); + glamor_priv->state = RENDER_STATE; + glamor_priv->render_idle_cnt = 0; + if (saved_source_format) + source->format = saved_source_format; + glamor_put_dispatch(glamor_priv); + + ret = TRUE; + return ret; } PicturePtr @@ -1472,411 +1475,412 @@ glamor_convert_gradient_picture(ScreenPtr screen, int x_source, int y_source, int width, int height) { - PixmapPtr pixmap; - PicturePtr dst = NULL; - int error; - PictFormatShort format; - if (!source->pDrawable) - format = PICT_a8r8g8b8; - else - format = source->format; + PixmapPtr pixmap; + PicturePtr dst = NULL; + int error; + PictFormatShort format; + + if (!source->pDrawable) + format = PICT_a8r8g8b8; + else + format = source->format; #ifdef GLAMOR_GRADIENT_SHADER - if (!source->pDrawable) { - if (source->pSourcePict->type == SourcePictTypeLinear) { - dst = glamor_generate_linear_gradient_picture(screen, - source, x_source, y_source, width, height, format); - } else if (source->pSourcePict->type == SourcePictTypeRadial) { - dst = glamor_generate_radial_gradient_picture(screen, - source, x_source, y_source, width, height, format); - } - - if (dst) { -#if 0 /* Debug to compare it to pixman, Enable it if needed. */ - glamor_compare_pictures(screen, source, - dst, x_source, y_source, width, height, - 0, 3); + if (!source->pDrawable) { + if (source->pSourcePict->type == SourcePictTypeLinear) { + dst = glamor_generate_linear_gradient_picture(screen, + source, x_source, + y_source, width, + height, format); + } + else if (source->pSourcePict->type == SourcePictTypeRadial) { + dst = glamor_generate_radial_gradient_picture(screen, + source, x_source, + y_source, width, + height, format); + } + + if (dst) { +#if 0 /* Debug to compare it to pixman, Enable it if needed. */ + glamor_compare_pictures(screen, source, + dst, x_source, y_source, width, height, + 0, 3); #endif - return dst; - } - } + return dst; + } + } #endif - pixmap = glamor_create_pixmap(screen, - width, - height, - PIXMAN_FORMAT_DEPTH(format), - GLAMOR_CREATE_PIXMAP_CPU); - - if (!pixmap) - return NULL; - - dst = CreatePicture(0, - &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), - format), - 0, 0, serverClient, &error); - glamor_destroy_pixmap(pixmap); - if (!dst) - return NULL; - - ValidatePicture(dst); - - fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source, - 0, 0, 0, 0, width, height); - return dst; + pixmap = glamor_create_pixmap(screen, + width, + height, + PIXMAN_FORMAT_DEPTH(format), + GLAMOR_CREATE_PIXMAP_CPU); + + if (!pixmap) + return NULL; + + dst = CreatePicture(0, + &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), 0, 0, serverClient, &error); + glamor_destroy_pixmap(pixmap); + if (!dst) + return NULL; + + ValidatePicture(dst); + + fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source, + 0, 0, 0, 0, width, height); + return dst; } Bool glamor_composite_clipped_region(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, - RegionPtr region, - int x_source, - int y_source, - int x_mask, - int y_mask, - int x_dest, - int y_dest) + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, + RegionPtr region, + int x_source, + int y_source, + int x_mask, int y_mask, int x_dest, int y_dest) { - ScreenPtr screen = dest->pDrawable->pScreen; - PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; - PicturePtr temp_src = source, temp_mask = mask; - glamor_pixmap_private *temp_src_priv = source_pixmap_priv; - glamor_pixmap_private *temp_mask_priv = mask_pixmap_priv; - int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; - BoxPtr extent; - glamor_composite_rect_t rect[10]; - glamor_composite_rect_t *prect = rect; - int prect_size = ARRAY_SIZE(rect); - int ok = FALSE; - int i; - int width; - int height; - BoxPtr box; - int nbox; - Bool two_pass_ca = FALSE; - - extent = RegionExtents(region); - box = RegionRects(region); - nbox = RegionNumRects(region); - width = extent->x2 - extent->x1; - height = extent->y2 - extent->y1; - - x_temp_src = x_source; - y_temp_src = y_source; - x_temp_mask = x_mask; - y_temp_mask = y_mask; - - DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", - x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); - - if (source_pixmap_priv) - source_pixmap = source_pixmap_priv->base.pixmap; - - if (mask_pixmap_priv) - mask_pixmap = mask_pixmap_priv->base.pixmap; - - /* XXX is it possible source mask have non-zero drawable.x/y? */ - if (source - && ((!source->pDrawable - && (source->pSourcePict->type != SourcePictTypeSolidFill)) - || (source->pDrawable - && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) - && (source_pixmap->drawable.width != width - || source_pixmap->drawable.height != height)))) { - temp_src = - glamor_convert_gradient_picture(screen, source, - extent->x1 + x_source - x_dest, - extent->y1 + y_source - y_dest, - width, height); - if (!temp_src) { - temp_src = source; - goto out; - } - temp_src_priv = glamor_get_pixmap_private((PixmapPtr)(temp_src->pDrawable)); - x_temp_src = - extent->x1 + x_dest; - y_temp_src = - extent->y1 + y_dest; - } - - if (mask - && - ((!mask->pDrawable - && (mask->pSourcePict->type != SourcePictTypeSolidFill)) - || (mask->pDrawable - && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv) - && (mask_pixmap->drawable.width != width - || mask_pixmap->drawable.height != height)))) { - /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity - * to do reduce one convertion. */ - temp_mask = - glamor_convert_gradient_picture(screen, mask, - extent->x1 + x_mask - x_dest, - extent->y1 + y_mask - y_dest, - width, height); - if (!temp_mask) { - temp_mask = mask; - goto out; - } - temp_mask_priv = glamor_get_pixmap_private((PixmapPtr)(temp_mask->pDrawable)); - x_temp_mask = - extent->x1 + x_dest; - y_temp_mask = - extent->y1 + y_dest; - } - /* Do two-pass PictOpOver componentAlpha, until we enable - * dual source color blending. - */ - - if (mask && mask->componentAlpha) { - if (op == PictOpOver) { - two_pass_ca = TRUE; - op = PictOpOutReverse; - } - } - - if (!mask && temp_src) { - if (glamor_composite_with_copy(op, temp_src, dest, - x_temp_src, y_temp_src, - x_dest, y_dest, region)) { - ok = TRUE; - goto out; - } - } - - /*XXXXX, self copy?*/ - - x_dest += dest->pDrawable->x; - y_dest += dest->pDrawable->y; - if (temp_src && temp_src->pDrawable) { - x_temp_src += temp_src->pDrawable->x; - y_temp_src += temp_src->pDrawable->y; - } - if (temp_mask && temp_mask->pDrawable) { - x_temp_mask += temp_mask->pDrawable->x; - y_temp_mask += temp_mask->pDrawable->y; - } - - if (nbox > ARRAY_SIZE(rect)) { - prect = calloc(nbox, sizeof(*prect)); - if (prect) - prect_size = nbox; - else { - prect = rect; - prect_size = ARRAY_SIZE(rect); - } - } - while(nbox) { - int box_cnt; - box_cnt = nbox > prect_size ? prect_size : nbox; - for (i = 0; i < box_cnt; i++) { - prect[i].x_src = box[i].x1 + x_temp_src - x_dest; - prect[i].y_src = box[i].y1 + y_temp_src - y_dest; - prect[i].x_mask = box[i].x1 + x_temp_mask - x_dest; - prect[i].y_mask = box[i].y1 + y_temp_mask - y_dest; - prect[i].x_dst = box[i].x1; - prect[i].y_dst = box[i].y1; - prect[i].width = box[i].x2 - box[i].x1; - prect[i].height = box[i].y2 - box[i].y1; - DEBUGF("dest %d %d \n", prect[i].x_dst, prect[i].y_dst); - } - ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest, - temp_src_priv, temp_mask_priv, - dest_pixmap_priv, - box_cnt, prect, two_pass_ca); - if (!ok) - break; - nbox -= box_cnt; - box += box_cnt; - } - - if (prect != rect) - free(prect); -out: - if (temp_src != source) - FreePicture(temp_src, 0); - if (temp_mask != mask) - FreePicture(temp_mask, 0); - - return ok; + ScreenPtr screen = dest->pDrawable->pScreen; + PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; + PicturePtr temp_src = source, temp_mask = mask; + glamor_pixmap_private *temp_src_priv = source_pixmap_priv; + glamor_pixmap_private *temp_mask_priv = mask_pixmap_priv; + int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; + BoxPtr extent; + glamor_composite_rect_t rect[10]; + glamor_composite_rect_t *prect = rect; + int prect_size = ARRAY_SIZE(rect); + int ok = FALSE; + int i; + int width; + int height; + BoxPtr box; + int nbox; + Bool two_pass_ca = FALSE; + + extent = RegionExtents(region); + box = RegionRects(region); + nbox = RegionNumRects(region); + width = extent->x2 - extent->x1; + height = extent->y2 - extent->y1; + + x_temp_src = x_source; + y_temp_src = y_source; + x_temp_mask = x_mask; + y_temp_mask = y_mask; + + DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", + x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + + if (source_pixmap_priv) + source_pixmap = source_pixmap_priv->base.pixmap; + + if (mask_pixmap_priv) + mask_pixmap = mask_pixmap_priv->base.pixmap; + + /* XXX is it possible source mask have non-zero drawable.x/y? */ + if (source + && ((!source->pDrawable + && (source->pSourcePict->type != SourcePictTypeSolidFill)) + || (source->pDrawable + && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) + && (source_pixmap->drawable.width != width + || source_pixmap->drawable.height != height)))) { + temp_src = + glamor_convert_gradient_picture(screen, source, + extent->x1 + x_source - x_dest, + extent->y1 + y_source - y_dest, + width, height); + if (!temp_src) { + temp_src = source; + goto out; + } + temp_src_priv = + glamor_get_pixmap_private((PixmapPtr) (temp_src->pDrawable)); + x_temp_src = -extent->x1 + x_dest; + y_temp_src = -extent->y1 + y_dest; + } + + if (mask + && + ((!mask->pDrawable + && (mask->pSourcePict->type != SourcePictTypeSolidFill)) + || (mask->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv) + && (mask_pixmap->drawable.width != width + || mask_pixmap->drawable.height != height)))) { + /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity + * to do reduce one convertion. */ + temp_mask = + glamor_convert_gradient_picture(screen, mask, + extent->x1 + x_mask - x_dest, + extent->y1 + y_mask - y_dest, + width, height); + if (!temp_mask) { + temp_mask = mask; + goto out; + } + temp_mask_priv = + glamor_get_pixmap_private((PixmapPtr) (temp_mask->pDrawable)); + x_temp_mask = -extent->x1 + x_dest; + y_temp_mask = -extent->y1 + y_dest; + } + /* Do two-pass PictOpOver componentAlpha, until we enable + * dual source color blending. + */ + + if (mask && mask->componentAlpha) { + if (op == PictOpOver) { + two_pass_ca = TRUE; + op = PictOpOutReverse; + } + } + + if (!mask && temp_src) { + if (glamor_composite_with_copy(op, temp_src, dest, + x_temp_src, y_temp_src, + x_dest, y_dest, region)) { + ok = TRUE; + goto out; + } + } + + /*XXXXX, self copy? */ + + x_dest += dest->pDrawable->x; + y_dest += dest->pDrawable->y; + if (temp_src && temp_src->pDrawable) { + x_temp_src += temp_src->pDrawable->x; + y_temp_src += temp_src->pDrawable->y; + } + if (temp_mask && temp_mask->pDrawable) { + x_temp_mask += temp_mask->pDrawable->x; + y_temp_mask += temp_mask->pDrawable->y; + } + + if (nbox > ARRAY_SIZE(rect)) { + prect = calloc(nbox, sizeof(*prect)); + if (prect) + prect_size = nbox; + else { + prect = rect; + prect_size = ARRAY_SIZE(rect); + } + } + while (nbox) { + int box_cnt; + + box_cnt = nbox > prect_size ? prect_size : nbox; + for (i = 0; i < box_cnt; i++) { + prect[i].x_src = box[i].x1 + x_temp_src - x_dest; + prect[i].y_src = box[i].y1 + y_temp_src - y_dest; + prect[i].x_mask = box[i].x1 + x_temp_mask - x_dest; + prect[i].y_mask = box[i].y1 + y_temp_mask - y_dest; + prect[i].x_dst = box[i].x1; + prect[i].y_dst = box[i].y1; + prect[i].width = box[i].x2 - box[i].x1; + prect[i].height = box[i].y2 - box[i].y1; + DEBUGF("dest %d %d \n", prect[i].x_dst, prect[i].y_dst); + } + ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest, + temp_src_priv, temp_mask_priv, + dest_pixmap_priv, + box_cnt, prect, two_pass_ca); + if (!ok) + break; + nbox -= box_cnt; + box += box_cnt; + } + + if (prect != rect) + free(prect); + out: + if (temp_src != source) + FreePicture(temp_src, 0); + if (temp_mask != mask) + FreePicture(temp_mask, 0); + + return ok; } static Bool _glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height, Bool fallback) + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height, Bool fallback) { - ScreenPtr screen = dest->pDrawable->pScreen; - glamor_pixmap_private *dest_pixmap_priv; - glamor_pixmap_private *source_pixmap_priv = - NULL, *mask_pixmap_priv = NULL; - PixmapPtr dest_pixmap = - glamor_get_drawable_pixmap(dest->pDrawable); - PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - Bool ret = TRUE; - RegionRec region; - BoxPtr extent; - int nbox, ok = FALSE; - PixmapPtr sub_dest_pixmap = NULL; - PixmapPtr sub_source_pixmap = NULL; - PixmapPtr sub_mask_pixmap = NULL; - int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y; - int source_x_off, source_y_off, saved_source_x, saved_source_y; - int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y; - DrawablePtr saved_dest_drawable; - DrawablePtr saved_source_drawable; - DrawablePtr saved_mask_drawable; - int force_clip = 0; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - - if (source->pDrawable) { - source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) - goto fail; - } - - if (mask && mask->pDrawable) { - mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) - goto fail; - } - - DEBUGF("source pixmap %p (%d %d) mask(%d %d) dest(%d %d) width %d height %d \n", - source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - goto fail; - } - - if (op >= ARRAY_SIZE(composite_op_info)) - goto fail; - - if (mask && mask->componentAlpha) { - if (op == PictOpAtop - || op == PictOpAtopReverse - || op == PictOpXor - || op >= PictOpSaturate) { - glamor_fallback - ("glamor_composite(): component alpha op %x\n", op); - goto fail; - } - } - - if ((source && source->filter >= PictFilterConvolution) - || (mask && mask->filter >= PictFilterConvolution)) { - glamor_fallback("glamor_composite(): unsupported filter\n"); - goto fail; - } - - if (!miComputeCompositeRegion(®ion, - source, mask, dest, - x_source + (source_pixmap ? source->pDrawable->x : 0), - y_source + (source_pixmap ? source->pDrawable->y : 0), - x_mask + (mask_pixmap ? mask->pDrawable->x : 0), - y_mask + (mask_pixmap ? mask->pDrawable->y : 0), - x_dest + dest->pDrawable->x, - y_dest + dest->pDrawable->y, - width, - height)) { - ret = TRUE; - goto done; - } - - nbox = REGION_NUM_RECTS(®ion); - DEBUGF("first clipped when compositing.\n"); - DEBUGRegionPrint(®ion); - extent = RegionExtents(®ion); - if (nbox == 0) { - ret = TRUE; - goto done; - } - /* If destination is not a large pixmap, but the region is larger - * than texture size limitation, and source or mask is memory pixmap, - * then there may be need to load a large memory pixmap to a - * texture, and this is not permitted. Then we force to clip the - * destination and make sure latter will not upload a large memory - * pixmap. */ - if (!glamor_check_fbo_size(glamor_priv, - extent->x2 - extent->x1, extent->y2 - extent->y1) - && (dest_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) - && ((source_pixmap_priv - && (source_pixmap_priv->type == GLAMOR_MEMORY || source->repeatType == RepeatPad)) - || (mask_pixmap_priv - && (mask_pixmap_priv->type == GLAMOR_MEMORY || mask->repeatType == RepeatPad)) - || (!source_pixmap_priv - && (source->pSourcePict->type != SourcePictTypeSolidFill)) - || (!mask_pixmap_priv && mask - && mask->pSourcePict->type != SourcePictTypeSolidFill))) - force_clip = 1; - - if (force_clip || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE - || (source_pixmap_priv - && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) - || (mask_pixmap_priv - && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)) - ok = glamor_composite_largepixmap_region(op, - source, mask, dest, - source_pixmap_priv, - mask_pixmap_priv, - dest_pixmap_priv, - ®ion, force_clip, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest, - width, height); - else - ok = glamor_composite_clipped_region(op, source, - mask, dest, - source_pixmap_priv, - mask_pixmap_priv, - dest_pixmap_priv, - ®ion, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest); - - REGION_UNINIT(dest->pDrawable->pScreen, ®ion); - - if (ok) - goto done; -fail: - - if (!fallback - && glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable) - && (!source_pixmap - || glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable)) - && (!mask_pixmap - || glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) { - ret = FALSE; - goto done; - } - - glamor_fallback - ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", - source, source->pDrawable, - source->pDrawable ? source->pDrawable->width : 0, - source->pDrawable ? source->pDrawable->height : 0, mask, - (!mask) ? NULL : mask->pDrawable, (!mask - || !mask->pDrawable) ? 0 : - mask->pDrawable->width, (!mask - || !mask-> - pDrawable) ? 0 : mask->pDrawable-> - height, glamor_get_picture_location(source), - glamor_get_picture_location(mask), dest, dest->pDrawable, - dest->pDrawable->width, dest->pDrawable->height, - glamor_get_picture_location(dest)); + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_pixmap_private *dest_pixmap_priv; + glamor_pixmap_private *source_pixmap_priv = NULL, *mask_pixmap_priv = NULL; + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + Bool ret = TRUE; + RegionRec region; + BoxPtr extent; + int nbox, ok = FALSE; + PixmapPtr sub_dest_pixmap = NULL; + PixmapPtr sub_source_pixmap = NULL; + PixmapPtr sub_mask_pixmap = NULL; + int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y; + int source_x_off, source_y_off, saved_source_x, saved_source_y; + int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y; + DrawablePtr saved_dest_drawable; + DrawablePtr saved_source_drawable; + DrawablePtr saved_mask_drawable; + int force_clip = 0; + + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + + if (source->pDrawable) { + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; + } + + if (mask && mask->pDrawable) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; + } + + DEBUGF + ("source pixmap %p (%d %d) mask(%d %d) dest(%d %d) width %d height %d \n", + source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest, + width, height); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + goto fail; + } + + if (op >= ARRAY_SIZE(composite_op_info)) + goto fail; + + if (mask && mask->componentAlpha) { + if (op == PictOpAtop + || op == PictOpAtopReverse + || op == PictOpXor || op >= PictOpSaturate) { + glamor_fallback("glamor_composite(): component alpha op %x\n", op); + goto fail; + } + } + + if ((source && source->filter >= PictFilterConvolution) + || (mask && mask->filter >= PictFilterConvolution)) { + glamor_fallback("glamor_composite(): unsupported filter\n"); + goto fail; + } + + if (!miComputeCompositeRegion(®ion, + source, mask, dest, + x_source + + (source_pixmap ? source->pDrawable->x : 0), + y_source + + (source_pixmap ? source->pDrawable->y : 0), + x_mask + + (mask_pixmap ? mask->pDrawable->x : 0), + y_mask + + (mask_pixmap ? mask->pDrawable->y : 0), + x_dest + dest->pDrawable->x, + y_dest + dest->pDrawable->y, width, height)) { + ret = TRUE; + goto done; + } + + nbox = REGION_NUM_RECTS(®ion); + DEBUGF("first clipped when compositing.\n"); + DEBUGRegionPrint(®ion); + extent = RegionExtents(®ion); + if (nbox == 0) { + ret = TRUE; + goto done; + } + /* If destination is not a large pixmap, but the region is larger + * than texture size limitation, and source or mask is memory pixmap, + * then there may be need to load a large memory pixmap to a + * texture, and this is not permitted. Then we force to clip the + * destination and make sure latter will not upload a large memory + * pixmap. */ + if (!glamor_check_fbo_size(glamor_priv, + extent->x2 - extent->x1, extent->y2 - extent->y1) + && (dest_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) + && ((source_pixmap_priv + && (source_pixmap_priv->type == GLAMOR_MEMORY || + source->repeatType == RepeatPad)) + || (mask_pixmap_priv && + (mask_pixmap_priv->type == GLAMOR_MEMORY || + mask->repeatType == RepeatPad)) + || (!source_pixmap_priv && + (source->pSourcePict->type != SourcePictTypeSolidFill)) + || (!mask_pixmap_priv && mask && + mask->pSourcePict->type != SourcePictTypeSolidFill))) + force_clip = 1; + + if (force_clip || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE + || (source_pixmap_priv + && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) + || (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)) + ok = glamor_composite_largepixmap_region(op, + source, mask, dest, + source_pixmap_priv, + mask_pixmap_priv, + dest_pixmap_priv, + ®ion, force_clip, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, width, height); + else + ok = glamor_composite_clipped_region(op, source, + mask, dest, + source_pixmap_priv, + mask_pixmap_priv, + dest_pixmap_priv, + ®ion, + x_source, y_source, + x_mask, y_mask, x_dest, y_dest); + + REGION_UNINIT(dest->pDrawable->pScreen, ®ion); + + if (ok) + goto done; + fail: + + if (!fallback && glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable) + && (!source_pixmap + || glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable)) + && (!mask_pixmap + || glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) { + ret = FALSE; + goto done; + } + + glamor_fallback + ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", + source, source->pDrawable, + source->pDrawable ? source->pDrawable->width : 0, + source->pDrawable ? source->pDrawable->height : 0, mask, + (!mask) ? NULL : mask->pDrawable, (!mask + || !mask->pDrawable) ? 0 : + mask->pDrawable->width, (!mask + || !mask->pDrawable) ? 0 : mask-> + pDrawable->height, glamor_get_picture_location(source), + glamor_get_picture_location(mask), dest, dest->pDrawable, + dest->pDrawable->width, dest->pDrawable->height, + glamor_get_picture_location(dest)); #define GET_SUB_PICTURE(p, access) do { \ glamor_get_drawable_deltas(p->pDrawable, p ##_pixmap, \ @@ -1897,32 +1901,28 @@ fail: x_ ##p = 0; \ y_ ##p = 0; \ } } while(0) - GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); - if (source->pDrawable && !source->transform) - GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO); - if (mask && mask->pDrawable && !mask->transform) - GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); - - if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { - if (source_pixmap == dest_pixmap || glamor_prepare_access_picture - (source, GLAMOR_ACCESS_RO)) { - if (!mask - || glamor_prepare_access_picture(mask, - GLAMOR_ACCESS_RO)) - { - fbComposite(op, - source, mask, dest, - x_source, y_source, - x_mask, y_mask, x_dest, - y_dest, width, height); - if (mask) - glamor_finish_access_picture(mask, GLAMOR_ACCESS_RO); - } - if (source_pixmap != dest_pixmap) - glamor_finish_access_picture(source, GLAMOR_ACCESS_RO); - } - glamor_finish_access_picture(dest, GLAMOR_ACCESS_RW); - } + GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); + if (source->pDrawable && !source->transform) + GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO); + if (mask && mask->pDrawable && !mask->transform) + GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); + + if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { + if (source_pixmap == dest_pixmap || glamor_prepare_access_picture + (source, GLAMOR_ACCESS_RO)) { + if (!mask || glamor_prepare_access_picture(mask, GLAMOR_ACCESS_RO)) { + fbComposite(op, + source, mask, dest, + x_source, y_source, + x_mask, y_mask, x_dest, y_dest, width, height); + if (mask) + glamor_finish_access_picture(mask, GLAMOR_ACCESS_RO); + } + if (source_pixmap != dest_pixmap) + glamor_finish_access_picture(source, GLAMOR_ACCESS_RO); + } + glamor_finish_access_picture(dest, GLAMOR_ACCESS_RW); + } #define PUT_SUB_PICTURE(p, access) do { \ if (sub_ ##p ##_pixmap != NULL) { \ @@ -1938,198 +1938,196 @@ fail: y_ ##p + p ##_y_off + p->pDrawable->y, \ width, height, access); \ }} while(0) - if (mask && mask->pDrawable) - PUT_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); - if (source->pDrawable) - PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO); - PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); - done: - return ret; + if (mask && mask->pDrawable) + PUT_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); + if (source->pDrawable) + PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO); + PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); + done: + return ret; } void glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height) + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) { - _glamor_composite(op, source, mask, dest, x_source, y_source, - x_mask, y_mask, x_dest, y_dest, width, height, - TRUE); + _glamor_composite(op, source, mask, dest, x_source, y_source, + x_mask, y_mask, x_dest, y_dest, width, height, TRUE); } Bool glamor_composite_nf(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height) + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) { - return _glamor_composite(op, source, mask, dest, x_source, y_source, - x_mask, y_mask, x_dest, y_dest, width, height, - FALSE); + return _glamor_composite(op, source, mask, dest, x_source, y_source, + x_mask, y_mask, x_dest, y_dest, width, height, + FALSE); } static void glamor_get_src_rect_extent(int nrect, - glamor_composite_rect_t *rects, - BoxPtr extent) + glamor_composite_rect_t *rects, BoxPtr extent) { - extent->x1 = MAXSHORT; - extent->y1 = MAXSHORT; - extent->x2 = MINSHORT; - extent->y2 = MINSHORT; - - while(nrect--) { - if (extent->x1 > rects->x_src) - extent->x1 = rects->x_src; - if (extent->y1 > rects->y_src) - extent->y1 = rects->y_src; - if (extent->x2 < rects->x_src + rects->width) - extent->x2 = rects->x_src + rects->width; - if (extent->y2 < rects->y_src + rects->height) - extent->y2 = rects->y_src + rects->height; - rects++; - } + extent->x1 = MAXSHORT; + extent->y1 = MAXSHORT; + extent->x2 = MINSHORT; + extent->y2 = MINSHORT; + + while (nrect--) { + if (extent->x1 > rects->x_src) + extent->x1 = rects->x_src; + if (extent->y1 > rects->y_src) + extent->y1 = rects->y_src; + if (extent->x2 < rects->x_src + rects->width) + extent->x2 = rects->x_src + rects->width; + if (extent->y2 < rects->y_src + rects->height) + extent->y2 = rects->y_src + rects->height; + rects++; + } } static void glamor_composite_src_rect_translate(int nrect, - glamor_composite_rect_t *rects, - int x, int y) + glamor_composite_rect_t *rects, + int x, int y) { - while(nrect--) { - rects->x_src += x; - rects->y_src += y; - rects++; - } + while (nrect--) { + rects->x_src += x; + rects->y_src += y; + rects++; + } } void glamor_composite_glyph_rects(CARD8 op, - PicturePtr src, PicturePtr mask, PicturePtr dst, - int nrect, glamor_composite_rect_t * rects) + PicturePtr src, PicturePtr mask, PicturePtr dst, + int nrect, glamor_composite_rect_t *rects) { - int n; - PicturePtr temp_src = NULL; - glamor_composite_rect_t *r; - - ValidatePicture(src); - ValidatePicture(dst); - if (!(glamor_is_large_picture(src) - || (mask && glamor_is_large_picture(mask)) - || glamor_is_large_picture(dst))) { - glamor_pixmap_private *src_pixmap_priv = NULL; - glamor_pixmap_private *mask_pixmap_priv = NULL; - glamor_pixmap_private *dst_pixmap_priv; - glamor_pixmap_private *temp_src_priv = NULL; - BoxRec src_extent; - - dst_pixmap_priv = glamor_get_pixmap_private - (glamor_get_drawable_pixmap(dst->pDrawable)); - - if (mask && mask->pDrawable) - mask_pixmap_priv = glamor_get_pixmap_private - (glamor_get_drawable_pixmap(mask->pDrawable)); - if (src->pDrawable) - src_pixmap_priv = glamor_get_pixmap_private - (glamor_get_drawable_pixmap(src->pDrawable)); - - if (!src->pDrawable - && (src->pSourcePict->type != SourcePictTypeSolidFill)) { - glamor_get_src_rect_extent(nrect, rects, &src_extent); - temp_src = glamor_convert_gradient_picture(dst->pDrawable->pScreen, - src, - src_extent.x1, src_extent.y1, - src_extent.x2 - src_extent.x1, - src_extent.y2 - src_extent.y1); - if (!temp_src) - goto fallback; - - temp_src_priv = glamor_get_pixmap_private - ((PixmapPtr)(temp_src->pDrawable)); - glamor_composite_src_rect_translate(nrect, rects, - -src_extent.x1, -src_extent.y1); - } else { - temp_src = src; - temp_src_priv = src_pixmap_priv; - } - - if (mask && mask->componentAlpha) { - if (op == PictOpOver) { - if (glamor_composite_with_shader(PictOpOutReverse, - temp_src, mask, dst, temp_src_priv, - mask_pixmap_priv, dst_pixmap_priv, nrect, rects, - TRUE)) - goto done; - } - } else { - if (glamor_composite_with_shader(op, temp_src, mask, dst, temp_src_priv, - mask_pixmap_priv, dst_pixmap_priv, nrect, rects, FALSE)) - goto done; - } - } -fallback: - n = nrect; - r = rects; - - while (n--) { - CompositePicture(op, - temp_src ? temp_src : src, - mask, - dst, - r->x_src, r->y_src, - r->x_mask, r->y_mask, - r->x_dst, r->y_dst, r->width, r->height); - r++; - } - -done: - if (temp_src && temp_src != src) - FreePicture(temp_src, 0); + int n; + PicturePtr temp_src = NULL; + glamor_composite_rect_t *r; + + ValidatePicture(src); + ValidatePicture(dst); + if (!(glamor_is_large_picture(src) + || (mask && glamor_is_large_picture(mask)) + || glamor_is_large_picture(dst))) { + glamor_pixmap_private *src_pixmap_priv = NULL; + glamor_pixmap_private *mask_pixmap_priv = NULL; + glamor_pixmap_private *dst_pixmap_priv; + glamor_pixmap_private *temp_src_priv = NULL; + BoxRec src_extent; + + dst_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(dst->pDrawable)); + + if (mask && mask->pDrawable) + mask_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(mask->pDrawable)); + if (src->pDrawable) + src_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(src->pDrawable)); + + if (!src->pDrawable + && (src->pSourcePict->type != SourcePictTypeSolidFill)) { + glamor_get_src_rect_extent(nrect, rects, &src_extent); + temp_src = glamor_convert_gradient_picture(dst->pDrawable->pScreen, + src, + src_extent.x1, + src_extent.y1, + src_extent.x2 - + src_extent.x1, + src_extent.y2 - + src_extent.y1); + if (!temp_src) + goto fallback; + + temp_src_priv = glamor_get_pixmap_private + ((PixmapPtr) (temp_src->pDrawable)); + glamor_composite_src_rect_translate(nrect, rects, + -src_extent.x1, -src_extent.y1); + } + else { + temp_src = src; + temp_src_priv = src_pixmap_priv; + } + + if (mask && mask->componentAlpha) { + if (op == PictOpOver) { + if (glamor_composite_with_shader(PictOpOutReverse, + temp_src, mask, dst, + temp_src_priv, + mask_pixmap_priv, + dst_pixmap_priv, nrect, rects, + TRUE)) + goto done; + } + } + else { + if (glamor_composite_with_shader + (op, temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, + dst_pixmap_priv, nrect, rects, FALSE)) + goto done; + } + } + fallback: + n = nrect; + r = rects; + + while (n--) { + CompositePicture(op, + temp_src ? temp_src : src, + mask, + dst, + r->x_src, r->y_src, + r->x_mask, r->y_mask, + r->x_dst, r->y_dst, r->width, r->height); + r++; + } + + done: + if (temp_src && temp_src != src) + FreePicture(temp_src, 0); } static Bool -_glamor_composite_rects (CARD8 op, - PicturePtr pDst, - xRenderColor *color, - int nRect, - xRectangle *rects, - Bool fallback) +_glamor_composite_rects(CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, xRectangle *rects, Bool fallback) { - miCompositeRects(op, pDst, color, nRect, rects); - return TRUE; + miCompositeRects(op, pDst, color, nRect, rects); + return TRUE; } void -glamor_composite_rects (CARD8 op, - PicturePtr pDst, - xRenderColor *color, - int nRect, - xRectangle *rects) +glamor_composite_rects(CARD8 op, + PicturePtr pDst, + xRenderColor *color, int nRect, xRectangle *rects) { - _glamor_composite_rects(op, pDst, color, nRect, rects, TRUE); + _glamor_composite_rects(op, pDst, color, nRect, rects, TRUE); } Bool -glamor_composite_rects_nf (CARD8 op, - PicturePtr pDst, - xRenderColor *color, - int nRect, - xRectangle *rects) +glamor_composite_rects_nf(CARD8 op, + PicturePtr pDst, + xRenderColor *color, int nRect, xRectangle *rects) { - return _glamor_composite_rects(op, pDst, color, nRect, rects, FALSE); + return _glamor_composite_rects(op, pDst, color, nRect, rects, FALSE); } -#endif /* RENDER */ +#endif /* RENDER */ |