1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984 |
- /*
- * Copyright © 2009 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- * Zhigang Gong <zhigang.gong@linux.intel.com>
- * Junyan He <junyan.he@linux.intel.com>
- *
- */
- /** @file glamor_render.c
- *
- * Render acceleration implementation
- */
- #include "glamor_priv.h"
- #ifdef RENDER
- #include "mipict.h"
- #include "fbpict.h"
- #if 0
- //#define DEBUGF(str, ...) do {} while(0)
- #define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__)
- //#define DEBUGRegionPrint(x) do {} while (0)
- #define DEBUGRegionPrint RegionPrint
- #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},
- };
- #define RepeatFix 10
- static GLuint
- glamor_create_composite_fs(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(GL_FRAGMENT_SHADER, source);
- free(source);
- return prog;
- }
- static GLuint
- glamor_create_composite_vs(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(GL_VERTEX_SHADER, source);
- free(source);
- return prog;
- }
- static void
- glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
- 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_make_current(glamor_priv);
- vs = glamor_create_composite_vs(key);
- if (vs == 0)
- return;
- fs = glamor_create_composite_fs(key);
- if (fs == 0)
- return;
- prog = glCreateProgram();
- glAttachShader(prog, vs);
- glAttachShader(prog, fs);
- glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position");
- glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0");
- glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1");
- glamor_link_glsl_prog(screen, prog, "composite");
- shader->prog = prog;
- glUseProgram(prog);
- if (key->source == SHADER_SOURCE_SOLID) {
- shader->source_uniform_location = glGetUniformLocation(prog, "source");
- }
- else {
- source_sampler_uniform_location =
- glGetUniformLocation(prog, "source_sampler");
- glUniform1i(source_sampler_uniform_location, 0);
- shader->source_wh = glGetUniformLocation(prog, "source_wh");
- shader->source_repeat_mode =
- glGetUniformLocation(prog, "source_repeat_mode");
- }
- if (key->mask != SHADER_MASK_NONE) {
- if (key->mask == SHADER_MASK_SOLID) {
- shader->mask_uniform_location = glGetUniformLocation(prog, "mask");
- }
- else {
- mask_sampler_uniform_location =
- glGetUniformLocation(prog, "mask_sampler");
- glUniform1i(mask_sampler_uniform_location, 1);
- shader->mask_wh = glGetUniformLocation(prog, "mask_wh");
- shader->mask_repeat_mode =
- glGetUniformLocation(prog, "mask_repeat_mode");
- }
- }
- }
- static glamor_composite_shader *
- glamor_lookup_composite_shader(ScreenPtr screen, struct
- shader_key
- *key)
- {
- 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);
- 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;
- }
- }
- void
- glamor_init_composite_shaders(ScreenPtr screen)
- {
- glamor_screen_private *glamor_priv;
- unsigned short *eb;
- int eb_size;
- glamor_priv = glamor_get_screen_private(screen);
- glamor_make_current(glamor_priv);
- glGenBuffers(1, &glamor_priv->ebo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
- eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2;
- eb = XNFalloc(eb_size);
- glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
- free(eb);
- }
- void
- glamor_fini_composite_shaders(ScreenPtr screen)
- {
- glamor_screen_private *glamor_priv;
- glamor_composite_shader *shader;
- int i, j, k;
- glamor_priv = glamor_get_screen_private(screen);
- glamor_make_current(glamor_priv);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- 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)
- glDeleteProgram(shader->prog);
- }
- }
- static Bool
- glamor_set_composite_op(ScreenPtr screen,
- 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;
- }
- 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)
- {
- float wh[4];
- int repeat_type;
- glamor_make_current(glamor_priv);
- glActiveTexture(GL_TEXTURE0 + unit);
- glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex);
- repeat_type = picture->repeatType;
- switch (picture->repeatType) {
- case RepeatNone:
- if (glamor_priv->gl_flavor != GLAMOR_GL_ES2) {
- /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_BORDER);
- } else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- break;
- case RepeatNormal:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- break;
- case RepeatPad:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- break;
- case RepeatReflect:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
- break;
- }
- switch (picture->filter) {
- default:
- case PictFilterFast:
- case PictFilterNearest:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- break;
- case PictFilterGood:
- case PictFilterBest:
- case PictFilterBilinear:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- break;
- }
- /*
- * 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_EXACT_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))
- glUniform4fv(wh_location, 1, wh);
- else
- repeat_type -= RepeatFix;
- }
- glUniform1i(repeat_location, repeat_type);
- }
- static void
- glamor_set_composite_solid(float *color, GLint uniform_location)
- {
- 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;
- }
- 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);
- }
- 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)
- {
- 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);
- int vert_size;
- char *vbo_offset;
- float *vb;
- 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;
- glamor_make_current(glamor_priv);
- vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
- glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
- glamor_priv->vb_stride, vbo_offset);
- glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
- if (glamor_priv->has_source_coords) {
- glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
- GL_FLOAT, GL_FALSE,
- glamor_priv->vb_stride,
- vbo_offset + 2 * sizeof(float));
- glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
- }
- if (glamor_priv->has_mask_coords) {
- glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE,
- glamor_priv->vb_stride,
- vbo_offset + (glamor_priv->has_source_coords ?
- 4 : 2) * sizeof(float));
- glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
- }
- return vb;
- }
- static void
- glamor_flush_composite_rects(ScreenPtr screen)
- {
- glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
- glamor_make_current(glamor_priv);
- if (!glamor_priv->render_nr_verts)
- return;
- if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
- glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts,
- (glamor_priv->render_nr_verts * 3) / 2,
- GL_UNSIGNED_SHORT, NULL);
- } else {
- glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2,
- GL_UNSIGNED_SHORT, NULL);
- }
- }
- int pict_format_combine_tab[][3] = {
- {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)
- {
- 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)
- {
- 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)
- {
- 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 {
- if (PICT_FORMAT_A(source->format))
- key.source = SHADER_SOURCE_TEXTURE_ALPHA;
- else
- key.source = SHADER_SOURCE_TEXTURE;
- }
- 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 == GLAMOR_FBO_UNATTACHED) {
- #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
- source_status = GLAMOR_UPLOAD_PENDING;
- #else
- 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 == GLAMOR_FBO_UNATTACHED) {
- #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
- mask_status = GLAMOR_UPLOAD_PENDING;
- #else
- 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;
- }
- }
- }
- #endif
- /* If the source and mask are two differently-formatted views of
- * the same pixmap bits, and the pixmap was already uploaded (so
- * the dynamic code above doesn't apply), then fall back to
- * software. We should use texture views to fix this properly.
- */
- if (source_pixmap && source_pixmap == mask_pixmap &&
- source->format != mask->format) {
- goto fail;
- }
- /*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)
- {
- glamor_screen_private *glamor_priv;
- glamor_priv = dest_priv->base.glamor_priv;
- glamor_make_current(glamor_priv);
- glUseProgram(shader->prog);
- if (key->source == SHADER_SOURCE_SOLID) {
- glamor_set_composite_solid(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(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) {
- glDisable(GL_BLEND);
- }
- else {
- glEnable(GL_BLEND);
- glBlendFunc(op_info->source_blend, op_info->dest_blend);
- }
- }
- 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)
- {
- 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;
- GLfloat dst_xscale, dst_yscale;
- GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1;
- struct shader_key key, key_ca;
- 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 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);
- glamor_make_current(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);
- }
- }
- 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);
- }
- }
- nrect_max = MIN(nrect, GLAMOR_COMPOSITE_VBO_VERT_CNT / 4);
- while (nrect) {
- int mrect, rect_processed;
- int vb_stride;
- float *vertices;
- mrect = nrect > nrect_max ? nrect_max : nrect;
- vertices = glamor_setup_composite_vbo(screen, mrect * 4);
- 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);
- 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);
- vertices += 2;
- }
- glamor_priv->render_nr_verts += 4;
- rects++;
- /* We've incremented by one of our 4 verts, now do the other 3. */
- vertices += 3 * vb_stride;
- }
- glamor_put_vbo_space(screen);
- 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);
- }
- }
- glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
- glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
- glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
- glDisable(GL_BLEND);
- DEBUGF("finish rendering.\n");
- glamor_priv->state = RENDER_STATE;
- glamor_priv->render_idle_cnt = 0;
- if (saved_source_format)
- source->format = saved_source_format;
- ret = TRUE;
- return ret;
- }
- PicturePtr
- glamor_convert_gradient_picture(ScreenPtr screen,
- PicturePtr source,
- 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;
- #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);
- #endif
- 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;
- }
- 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)
- {
- 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 - dest->pDrawable->x,
- extent->y1 + y_source - y_dest - dest->pDrawable->y,
- 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 + dest->pDrawable->x;
- y_temp_src = -extent->y1 + y_dest + dest->pDrawable->y;
- }
- 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 - dest->pDrawable->x,
- extent->y1 + y_mask - y_dest - dest->pDrawable->y,
- 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 + dest->pDrawable->x;
- y_temp_mask = -extent->y1 + y_dest + dest->pDrawable->y;
- }
- /* 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)
- {
- 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, \
- & p ##_x_off, & p ##_y_off); \
- sub_ ##p ##_pixmap = glamor_get_sub_pixmap(p ##_pixmap, \
- x_ ##p + p ##_x_off + p->pDrawable->x, \
- y_ ##p + p ##_y_off + p->pDrawable->y, \
- width, height, access); \
- if (sub_ ##p ##_pixmap != NULL) { \
- saved_ ##p ##_drawable = p->pDrawable; \
- saved_ ##p ##_x = x_ ##p; \
- saved_ ##p ##_y = y_ ##p; \
- if (p->pCompositeClip) \
- pixman_region_translate (p->pCompositeClip, \
- -p->pDrawable->x - x_ ##p, \
- -p->pDrawable->y - y_ ##p); \
- p->pDrawable = &sub_ ##p ##_pixmap->drawable; \
- 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) &&
- glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO) &&
- 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);
- }
- glamor_finish_access_picture(mask);
- glamor_finish_access_picture(source);
- glamor_finish_access_picture(dest);
- #define PUT_SUB_PICTURE(p, access) do { \
- if (sub_ ##p ##_pixmap != NULL) { \
- x_ ##p = saved_ ##p ##_x; \
- y_ ##p = saved_ ##p ##_y; \
- p->pDrawable = saved_ ##p ##_drawable; \
- if (p->pCompositeClip) \
- pixman_region_translate (p->pCompositeClip, \
- p->pDrawable->x + x_ ##p, \
- p->pDrawable->y + y_ ##p); \
- glamor_put_sub_pixmap(sub_ ##p ##_pixmap, p ##_pixmap, \
- x_ ##p + p ##_x_off + p->pDrawable->x, \
- 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;
- }
- 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)
- {
- _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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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(op, pDst, color, nRect, rects, TRUE);
- }
- Bool
- glamor_composite_rects_nf(CARD8 op,
- PicturePtr pDst,
- xRenderColor *color, int nRect, xRectangle *rects)
- {
- return _glamor_composite_rects(op, pDst, color, nRect, rects, FALSE);
- }
- #endif /* RENDER */
|