12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418 |
- #include <stdlib.h>
- #include "glamor_priv.h"
- /**
- * Clip the boxes regards to each pixmap's block array.
- *
- * Should translate the region to relative coords to the pixmap,
- * start at (0,0).
- */
- #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 glamor_pixmap_clipped_regions *
- __glamor_compute_clipped_regions(int block_w,
- int block_h,
- int block_stride,
- int x, int y,
- int w, int h,
- RegionPtr region,
- int *n_region, int reverse, int upsidedown)
- {
- glamor_pixmap_clipped_regions *clipped_regions;
- BoxPtr extent;
- int start_x, start_y, end_x, end_y;
- int start_block_x, start_block_y;
- int end_block_x, end_block_y;
- int loop_start_block_x, loop_start_block_y;
- int loop_end_block_x, loop_end_block_y;
- int loop_block_stride;
- int i, j, delta_i, delta_j;
- RegionRec temp_region;
- RegionPtr current_region;
- int block_idx;
- int k = 0;
- int temp_block_idx;
- extent = RegionExtents(region);
- start_x = MAX(x, extent->x1);
- start_y = MAX(y, extent->y1);
- end_x = MIN(x + w, extent->x2);
- end_y = MIN(y + h, extent->y2);
- DEBUGF("start compute clipped regions:\n");
- DEBUGF("block w %d h %d x %d y %d w %d h %d, block_stride %d \n",
- block_w, block_h, x, y, w, h, block_stride);
- DEBUGRegionPrint(region);
- DEBUGF("start_x %d start_y %d end_x %d end_y %d \n", start_x, start_y,
- end_x, end_y);
- if (start_x >= end_x || start_y >= end_y) {
- *n_region = 0;
- return NULL;
- }
- start_block_x = (start_x - x) / block_w;
- start_block_y = (start_y - y) / block_h;
- end_block_x = (end_x - x) / block_w;
- end_block_y = (end_y - y) / block_h;
- clipped_regions = calloc((end_block_x - start_block_x + 1)
- * (end_block_y - start_block_y + 1),
- sizeof(*clipped_regions));
- DEBUGF("startx %d starty %d endx %d endy %d \n",
- start_x, start_y, end_x, end_y);
- DEBUGF("start_block_x %d end_block_x %d \n", start_block_x, end_block_x);
- DEBUGF("start_block_y %d end_block_y %d \n", start_block_y, end_block_y);
- if (!reverse) {
- loop_start_block_x = start_block_x;
- loop_end_block_x = end_block_x + 1;
- delta_i = 1;
- }
- else {
- loop_start_block_x = end_block_x;
- loop_end_block_x = start_block_x - 1;
- delta_i = -1;
- }
- if (!upsidedown) {
- loop_start_block_y = start_block_y;
- loop_end_block_y = end_block_y + 1;
- delta_j = 1;
- }
- else {
- loop_start_block_y = end_block_y;
- loop_end_block_y = start_block_y - 1;
- delta_j = -1;
- }
- loop_block_stride = delta_j * block_stride;
- block_idx = (loop_start_block_y - delta_j) * block_stride;
- for (j = loop_start_block_y; j != loop_end_block_y; j += delta_j) {
- block_idx += loop_block_stride;
- temp_block_idx = block_idx + loop_start_block_x;
- for (i = loop_start_block_x;
- i != loop_end_block_x; i += delta_i, temp_block_idx += delta_i) {
- BoxRec temp_box;
- temp_box.x1 = x + i * block_w;
- temp_box.y1 = y + j * block_h;
- temp_box.x2 = MIN(temp_box.x1 + block_w, end_x);
- temp_box.y2 = MIN(temp_box.y1 + block_h, end_y);
- RegionInitBoxes(&temp_region, &temp_box, 1);
- DEBUGF("block idx %d \n", temp_block_idx);
- DEBUGRegionPrint(&temp_region);
- current_region = RegionCreate(NULL, 4);
- RegionIntersect(current_region, &temp_region, region);
- DEBUGF("i %d j %d region: \n", i, j);
- DEBUGRegionPrint(current_region);
- if (RegionNumRects(current_region)) {
- clipped_regions[k].region = current_region;
- clipped_regions[k].block_idx = temp_block_idx;
- k++;
- }
- else
- RegionDestroy(current_region);
- RegionUninit(&temp_region);
- }
- }
- *n_region = k;
- return clipped_regions;
- }
- /**
- * Do a two round clipping,
- * first is to clip the region regard to current pixmap's
- * block array. Then for each clipped region, do a inner
- * block clipping. This is to make sure the final result
- * will be shapped by inner_block_w and inner_block_h, and
- * the final region also will not cross the pixmap's block
- * boundary.
- *
- * This is mainly used by transformation support when do
- * compositing.
- */
- glamor_pixmap_clipped_regions *
- glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv,
- RegionPtr region,
- int *n_region,
- int inner_block_w, int inner_block_h,
- int reverse, int upsidedown)
- {
- glamor_pixmap_clipped_regions *clipped_regions, *inner_regions,
- *result_regions;
- int i, j, x, y, k, inner_n_regions;
- int width, height;
- glamor_pixmap_private_large_t *priv;
- priv = &pixmap_priv->large;
- DEBUGF("ext called \n");
- if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
- clipped_regions = calloc(1, sizeof(*clipped_regions));
- if (clipped_regions == NULL) {
- *n_region = 0;
- return NULL;
- }
- clipped_regions[0].region = RegionCreate(NULL, 1);
- clipped_regions[0].block_idx = 0;
- RegionCopy(clipped_regions[0].region, region);
- *n_region = 1;
- priv->block_w = priv->base.pixmap->drawable.width;
- priv->block_h = priv->base.pixmap->drawable.height;
- priv->box_array = &priv->box;
- priv->box.x1 = priv->box.y1 = 0;
- priv->box.x2 = priv->block_w;
- priv->box.y2 = priv->block_h;
- }
- else {
- clipped_regions = __glamor_compute_clipped_regions(priv->block_w,
- priv->block_h,
- priv->block_wcnt,
- 0, 0,
- priv->base.pixmap->
- drawable.width,
- priv->base.pixmap->
- drawable.height,
- region, n_region,
- reverse, upsidedown);
- if (clipped_regions == NULL) {
- *n_region = 0;
- return NULL;
- }
- }
- if (inner_block_w >= priv->block_w && inner_block_h >= priv->block_h)
- return clipped_regions;
- result_regions = calloc(*n_region
- * ((priv->block_w + inner_block_w - 1) /
- inner_block_w)
- * ((priv->block_h + inner_block_h - 1) /
- inner_block_h), sizeof(*result_regions));
- k = 0;
- for (i = 0; i < *n_region; i++) {
- x = priv->box_array[clipped_regions[i].block_idx].x1;
- y = priv->box_array[clipped_regions[i].block_idx].y1;
- width = priv->box_array[clipped_regions[i].block_idx].x2 - x;
- height = priv->box_array[clipped_regions[i].block_idx].y2 - y;
- inner_regions = __glamor_compute_clipped_regions(inner_block_w,
- inner_block_h,
- 0, x, y,
- width,
- height,
- clipped_regions[i].
- region,
- &inner_n_regions,
- reverse, upsidedown);
- for (j = 0; j < inner_n_regions; j++) {
- result_regions[k].region = inner_regions[j].region;
- result_regions[k].block_idx = clipped_regions[i].block_idx;
- k++;
- }
- free(inner_regions);
- }
- *n_region = k;
- free(clipped_regions);
- return result_regions;
- }
- /*
- *
- * For the repeat pad mode, we can simply convert the region and
- * let the out-of-box region can cover the needed edge of the source/mask
- * Then apply a normal clip we can get what we want.
- */
- static RegionPtr
- _glamor_convert_pad_region(RegionPtr region, int w, int h)
- {
- RegionPtr pad_region;
- int nrect;
- BoxPtr box;
- int overlap;
- nrect = RegionNumRects(region);
- box = RegionRects(region);
- pad_region = RegionCreate(NULL, 4);
- if (pad_region == NULL)
- return NULL;
- while (nrect--) {
- BoxRec pad_box;
- RegionRec temp_region;
- pad_box = *box;
- if (pad_box.x1 < 0 && pad_box.x2 <= 0)
- pad_box.x2 = 1;
- else if (pad_box.x1 >= w && pad_box.x2 > w)
- pad_box.x1 = w - 1;
- if (pad_box.y1 < 0 && pad_box.y2 <= 0)
- pad_box.y2 = 1;
- else if (pad_box.y1 >= h && pad_box.y2 > h)
- pad_box.y1 = h - 1;
- RegionInitBoxes(&temp_region, &pad_box, 1);
- RegionAppend(pad_region, &temp_region);
- RegionUninit(&temp_region);
- box++;
- }
- RegionValidate(pad_region, &overlap);
- return pad_region;
- }
- /*
- * For one type of large pixmap, its one direction is not exceed the
- * size limitation, and in another word, on one direction it has only
- * one block.
- *
- * This case of reflect repeating, we can optimize it and avoid repeat
- * clip on that direction. We can just enlarge the repeat box and can
- * cover all the dest region on that direction. But latter, we need to
- * fixup the clipped result to get a correct coords for the subsequent
- * processing. This function is to do the coords correction.
- *
- * */
- static void
- _glamor_largepixmap_reflect_fixup(short *xy1, short *xy2, int wh)
- {
- int odd1, odd2;
- int c1, c2;
- if (*xy2 - *xy1 > wh) {
- *xy1 = 0;
- *xy2 = wh;
- return;
- }
- modulus(*xy1, wh, c1);
- odd1 = ((*xy1 - c1) / wh) & 0x1;
- modulus(*xy2, wh, c2);
- odd2 = ((*xy2 - c2) / wh) & 0x1;
- if (odd1 && odd2) {
- *xy1 = wh - c2;
- *xy2 = wh - c1;
- }
- else if (odd1 && !odd2) {
- *xy1 = 0;
- *xy2 = MAX(c2, wh - c1);
- }
- else if (!odd1 && odd2) {
- *xy2 = wh;
- *xy1 = MIN(c1, wh - c2);
- }
- else {
- *xy1 = c1;
- *xy2 = c2;
- }
- }
- /**
- * Clip the boxes regards to each pixmap's block array.
- *
- * Should translate the region to relative coords to the pixmap,
- * start at (0,0).
- *
- * @is_transform: if it is set, it has a transform matrix.
- *
- */
- static glamor_pixmap_clipped_regions *
- _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv,
- RegionPtr region, int *n_region,
- int repeat_type, int is_transform,
- int reverse, int upsidedown)
- {
- glamor_pixmap_clipped_regions *clipped_regions;
- BoxPtr extent;
- int i, j;
- RegionPtr current_region;
- int pixmap_width, pixmap_height;
- int m;
- BoxRec repeat_box;
- RegionRec repeat_region;
- int right_shift = 0;
- int down_shift = 0;
- int x_center_shift = 0, y_center_shift = 0;
- glamor_pixmap_private_large_t *priv;
- priv = &pixmap_priv->large;
- DEBUGRegionPrint(region);
- if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
- clipped_regions = calloc(1, sizeof(*clipped_regions));
- clipped_regions[0].region = RegionCreate(NULL, 1);
- clipped_regions[0].block_idx = 0;
- RegionCopy(clipped_regions[0].region, region);
- *n_region = 1;
- return clipped_regions;
- }
- pixmap_width = priv->base.pixmap->drawable.width;
- pixmap_height = priv->base.pixmap->drawable.height;
- if (repeat_type == 0 || repeat_type == RepeatPad) {
- RegionPtr saved_region = NULL;
- if (repeat_type == RepeatPad) {
- saved_region = region;
- region =
- _glamor_convert_pad_region(saved_region, pixmap_width,
- pixmap_height);
- if (region == NULL) {
- *n_region = 0;
- return NULL;
- }
- }
- clipped_regions = __glamor_compute_clipped_regions(priv->block_w,
- priv->block_h,
- priv->block_wcnt,
- 0, 0,
- priv->base.pixmap->
- drawable.width,
- priv->base.pixmap->
- drawable.height,
- region, n_region,
- reverse, upsidedown);
- if (saved_region)
- RegionDestroy(region);
- return clipped_regions;
- }
- extent = RegionExtents(region);
- x_center_shift = extent->x1 / pixmap_width;
- if (x_center_shift < 0)
- x_center_shift--;
- if (abs(x_center_shift) & 1)
- x_center_shift++;
- y_center_shift = extent->y1 / pixmap_height;
- if (y_center_shift < 0)
- y_center_shift--;
- if (abs(y_center_shift) & 1)
- y_center_shift++;
- if (extent->x1 < 0)
- right_shift = ((-extent->x1 + pixmap_width - 1) / pixmap_width);
- if (extent->y1 < 0)
- down_shift = ((-extent->y1 + pixmap_height - 1) / pixmap_height);
- if (right_shift != 0 || down_shift != 0) {
- if (repeat_type == RepeatReflect) {
- right_shift = (right_shift + 1) & ~1;
- down_shift = (down_shift + 1) & ~1;
- }
- RegionTranslate(region, right_shift * pixmap_width,
- down_shift * pixmap_height);
- }
- extent = RegionExtents(region);
- /* Tile a large pixmap to another large pixmap.
- * We can't use the target large pixmap as the
- * loop variable, instead we need to loop for all
- * the blocks in the tile pixmap.
- *
- * simulate repeat each single block to cover the
- * target's blocks. Two special case:
- * a block_wcnt == 1 or block_hcnt ==1, then we
- * only need to loop one direction as the other
- * direction is fully included in the first block.
- *
- * For the other cases, just need to start
- * from a proper shiftx/shifty, and then increase
- * y by tile_height each time to walk trhough the
- * target block and then walk trhough the target
- * at x direction by increate tile_width each time.
- *
- * This way, we can consolidate all the sub blocks
- * of the target boxes into one tile source's block.
- *
- * */
- m = 0;
- clipped_regions = calloc(priv->block_wcnt * priv->block_hcnt,
- sizeof(*clipped_regions));
- if (clipped_regions == NULL) {
- *n_region = 0;
- return NULL;
- }
- if (right_shift != 0 || down_shift != 0) {
- DEBUGF("region to be repeated shifted \n");
- DEBUGRegionPrint(region);
- }
- DEBUGF("repeat pixmap width %d height %d \n", pixmap_width, pixmap_height);
- DEBUGF("extent x1 %d y1 %d x2 %d y2 %d \n", extent->x1, extent->y1,
- extent->x2, extent->y2);
- for (j = 0; j < priv->block_hcnt; j++) {
- for (i = 0; i < priv->block_wcnt; i++) {
- int dx = pixmap_width;
- int dy = pixmap_height;
- int idx;
- int shift_x;
- int shift_y;
- int saved_y1, saved_y2;
- int x_idx = 0, y_idx = 0, saved_y_idx = 0;
- RegionRec temp_region;
- BoxRec reflect_repeat_box;
- BoxPtr valid_repeat_box;
- shift_x = (extent->x1 / pixmap_width) * pixmap_width;
- shift_y = (extent->y1 / pixmap_height) * pixmap_height;
- idx = j * priv->block_wcnt + i;
- if (repeat_type == RepeatReflect) {
- x_idx = (extent->x1 / pixmap_width);
- y_idx = (extent->y1 / pixmap_height);
- }
- /* Construct a rect to clip the target region. */
- repeat_box.x1 = shift_x + priv->box_array[idx].x1;
- repeat_box.y1 = shift_y + priv->box_array[idx].y1;
- if (priv->block_wcnt == 1) {
- repeat_box.x2 = extent->x2;
- dx = extent->x2 - repeat_box.x1;
- }
- else
- repeat_box.x2 = shift_x + priv->box_array[idx].x2;
- if (priv->block_hcnt == 1) {
- repeat_box.y2 = extent->y2;
- dy = extent->y2 - repeat_box.y1;
- }
- else
- repeat_box.y2 = shift_y + priv->box_array[idx].y2;
- current_region = RegionCreate(NULL, 4);
- RegionInit(&temp_region, NULL, 4);
- DEBUGF("init repeat box %d %d %d %d \n",
- repeat_box.x1, repeat_box.y1, repeat_box.x2, repeat_box.y2);
- if (repeat_type == RepeatNormal) {
- saved_y1 = repeat_box.y1;
- saved_y2 = repeat_box.y2;
- for (; repeat_box.x1 < extent->x2;
- repeat_box.x1 += dx, repeat_box.x2 += dx) {
- repeat_box.y1 = saved_y1;
- repeat_box.y2 = saved_y2;
- for (repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2;
- repeat_box.y1 < extent->y2;
- repeat_box.y1 += dy, repeat_box.y2 += dy) {
- RegionInitBoxes(&repeat_region, &repeat_box, 1);
- DEBUGF("Start to clip repeat region: \n");
- DEBUGRegionPrint(&repeat_region);
- RegionIntersect(&temp_region, &repeat_region, region);
- DEBUGF("clip result:\n");
- DEBUGRegionPrint(&temp_region);
- RegionAppend(current_region, &temp_region);
- RegionUninit(&repeat_region);
- }
- }
- }
- else if (repeat_type == RepeatReflect) {
- saved_y1 = repeat_box.y1;
- saved_y2 = repeat_box.y2;
- saved_y_idx = y_idx;
- for (;; repeat_box.x1 += dx, repeat_box.x2 += dx) {
- repeat_box.y1 = saved_y1;
- repeat_box.y2 = saved_y2;
- y_idx = saved_y_idx;
- reflect_repeat_box.x1 = (x_idx & 1) ?
- ((2 * x_idx + 1) * dx - repeat_box.x2) : repeat_box.x1;
- reflect_repeat_box.x2 = (x_idx & 1) ?
- ((2 * x_idx + 1) * dx - repeat_box.x1) : repeat_box.x2;
- valid_repeat_box = &reflect_repeat_box;
- if (valid_repeat_box->x1 >= extent->x2)
- break;
- for (repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2;;
- repeat_box.y1 += dy, repeat_box.y2 += dy) {
- DEBUGF("x_idx %d y_idx %d dx %d dy %d\n", x_idx, y_idx,
- dx, dy);
- DEBUGF("repeat box %d %d %d %d \n", repeat_box.x1,
- repeat_box.y1, repeat_box.x2, repeat_box.y2);
- if (priv->block_hcnt > 1) {
- reflect_repeat_box.y1 = (y_idx & 1) ?
- ((2 * y_idx + 1) * dy -
- repeat_box.y2) : repeat_box.y1;
- reflect_repeat_box.y2 =
- (y_idx & 1) ? ((2 * y_idx + 1) * dy -
- repeat_box.y1) : repeat_box.y2;
- }
- else {
- reflect_repeat_box.y1 = repeat_box.y1;
- reflect_repeat_box.y2 = repeat_box.y2;
- }
- DEBUGF("valid_repeat_box x1 %d y1 %d \n",
- valid_repeat_box->x1, valid_repeat_box->y1);
- if (valid_repeat_box->y1 >= extent->y2)
- break;
- RegionInitBoxes(&repeat_region, valid_repeat_box, 1);
- DEBUGF("start to clip repeat[reflect] region: \n");
- DEBUGRegionPrint(&repeat_region);
- RegionIntersect(&temp_region, &repeat_region, region);
- DEBUGF("result:\n");
- DEBUGRegionPrint(&temp_region);
- if (is_transform && RegionNumRects(&temp_region)) {
- BoxRec temp_box;
- BoxPtr temp_extent;
- temp_extent = RegionExtents(&temp_region);
- if (priv->block_wcnt > 1) {
- if (x_idx & 1) {
- temp_box.x1 =
- ((2 * x_idx + 1) * dx -
- temp_extent->x2);
- temp_box.x2 =
- ((2 * x_idx + 1) * dx -
- temp_extent->x1);
- }
- else {
- temp_box.x1 = temp_extent->x1;
- temp_box.x2 = temp_extent->x2;
- }
- modulus(temp_box.x1, pixmap_width, temp_box.x1);
- modulus(temp_box.x2, pixmap_width, temp_box.x2);
- if (temp_box.x2 == 0)
- temp_box.x2 = pixmap_width;
- }
- else {
- temp_box.x1 = temp_extent->x1;
- temp_box.x2 = temp_extent->x2;
- _glamor_largepixmap_reflect_fixup(&temp_box.x1,
- &temp_box.x2,
- pixmap_width);
- }
- if (priv->block_hcnt > 1) {
- if (y_idx & 1) {
- temp_box.y1 =
- ((2 * y_idx + 1) * dy -
- temp_extent->y2);
- temp_box.y2 =
- ((2 * y_idx + 1) * dy -
- temp_extent->y1);
- }
- else {
- temp_box.y1 = temp_extent->y1;
- temp_box.y2 = temp_extent->y2;
- }
- modulus(temp_box.y1, pixmap_height,
- temp_box.y1);
- modulus(temp_box.y2, pixmap_height,
- temp_box.y2);
- if (temp_box.y2 == 0)
- temp_box.y2 = pixmap_height;
- }
- else {
- temp_box.y1 = temp_extent->y1;
- temp_box.y2 = temp_extent->y2;
- _glamor_largepixmap_reflect_fixup(&temp_box.y1,
- &temp_box.y2,
- pixmap_height);
- }
- RegionInitBoxes(&temp_region, &temp_box, 1);
- RegionTranslate(&temp_region,
- x_center_shift * pixmap_width,
- y_center_shift * pixmap_height);
- DEBUGF("for transform result:\n");
- DEBUGRegionPrint(&temp_region);
- }
- RegionAppend(current_region, &temp_region);
- RegionUninit(&repeat_region);
- y_idx++;
- }
- x_idx++;
- }
- }
- DEBUGF("dx %d dy %d \n", dx, dy);
- if (RegionNumRects(current_region)) {
- if ((right_shift != 0 || down_shift != 0) &&
- !(is_transform && repeat_type == RepeatReflect))
- RegionTranslate(current_region, -right_shift * pixmap_width,
- -down_shift * pixmap_height);
- clipped_regions[m].region = current_region;
- clipped_regions[m].block_idx = idx;
- m++;
- }
- else
- RegionDestroy(current_region);
- RegionUninit(&temp_region);
- }
- }
- if (right_shift != 0 || down_shift != 0)
- RegionTranslate(region, -right_shift * pixmap_width,
- -down_shift * pixmap_height);
- *n_region = m;
- return clipped_regions;
- }
- glamor_pixmap_clipped_regions *
- glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region,
- int *n_region, int repeat_type,
- int reverse, int upsidedown)
- {
- return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type,
- 0, reverse, upsidedown);
- }
- /* XXX overflow still exist. maybe we need to change to use region32.
- * by default. Or just use region32 for repeat cases?
- **/
- glamor_pixmap_clipped_regions *
- glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv,
- struct pixman_transform *transform,
- RegionPtr region, int *n_region,
- int dx, int dy, int repeat_type,
- int reverse, int upsidedown)
- {
- BoxPtr temp_extent;
- struct pixman_box32 temp_box;
- struct pixman_box16 short_box;
- RegionPtr temp_region;
- glamor_pixmap_clipped_regions *ret;
- temp_region = RegionCreate(NULL, 4);
- temp_extent = RegionExtents(region);
- DEBUGF("dest region \n");
- DEBUGRegionPrint(region);
- /* dx/dy may exceed MAX SHORT. we have to use
- * a box32 to represent it.*/
- temp_box.x1 = temp_extent->x1 + dx;
- temp_box.x2 = temp_extent->x2 + dx;
- temp_box.y1 = temp_extent->y1 + dy;
- temp_box.y2 = temp_extent->y2 + dy;
- DEBUGF("source box %d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2,
- temp_box.y2);
- if (transform)
- glamor_get_transform_extent_from_box(&temp_box, transform);
- if (repeat_type == RepeatNone) {
- if (temp_box.x1 < 0)
- temp_box.x1 = 0;
- if (temp_box.y1 < 0)
- temp_box.y1 = 0;
- temp_box.x2 = MIN(temp_box.x2, priv->base.pixmap->drawable.width);
- temp_box.y2 = MIN(temp_box.y2, priv->base.pixmap->drawable.height);
- }
- /* Now copy back the box32 to a box16 box. */
- short_box.x1 = temp_box.x1;
- short_box.y1 = temp_box.y1;
- short_box.x2 = temp_box.x2;
- short_box.y2 = temp_box.y2;
- RegionInitBoxes(temp_region, &short_box, 1);
- DEBUGF("copy to temp source region \n");
- DEBUGRegionPrint(temp_region);
- ret = _glamor_compute_clipped_regions(priv,
- temp_region,
- n_region,
- repeat_type, 1, reverse, upsidedown);
- DEBUGF("n_regions = %d \n", *n_region);
- RegionDestroy(temp_region);
- return ret;
- }
- /*
- * As transform and repeatpad mode.
- * We may get a clipped result which in multipe regions.
- * It's not easy to do a 2nd round clipping just as we do
- * without transform/repeatPad. As it's not easy to reverse
- * the 2nd round clipping result with a transform/repeatPad mode,
- * or even impossible for some transformation.
- *
- * So we have to merge the fragmental region into one region
- * if the clipped result cross the region boundary.
- */
- static void
- glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv,
- int repeat_type,
- glamor_pixmap_clipped_regions *clipped_regions,
- int *n_regions, int *need_clean_fbo)
- {
- BoxPtr temp_extent;
- BoxRec temp_box, copy_box;
- RegionPtr temp_region;
- glamor_pixmap_private *temp_priv;
- PixmapPtr temp_pixmap;
- int overlap;
- int i;
- int pixmap_width, pixmap_height;
- glamor_pixmap_private_large_t *priv;
- priv = &pixmap_priv->large;
- pixmap_width = priv->base.pixmap->drawable.width;
- pixmap_height = priv->base.pixmap->drawable.height;
- temp_region = RegionCreate(NULL, 4);
- for (i = 0; i < *n_regions; i++) {
- DEBUGF("Region %d:\n", i);
- DEBUGRegionPrint(clipped_regions[i].region);
- RegionAppend(temp_region, clipped_regions[i].region);
- }
- RegionValidate(temp_region, &overlap);
- DEBUGF("temp region: \n");
- DEBUGRegionPrint(temp_region);
- temp_extent = RegionExtents(temp_region);
- temp_box = *temp_extent;
- DEBUGF("need copy region: \n");
- DEBUGF("%d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2,
- temp_box.y2);
- temp_pixmap =
- glamor_create_pixmap(priv->base.pixmap->drawable.pScreen,
- temp_box.x2 - temp_box.x1,
- temp_box.y2 - temp_box.y1,
- priv->base.pixmap->drawable.depth,
- GLAMOR_CREATE_PIXMAP_FIXUP);
- if (temp_pixmap == NULL) {
- assert(0);
- return;
- }
- temp_priv = glamor_get_pixmap_private(temp_pixmap);
- assert(temp_priv->type != GLAMOR_TEXTURE_LARGE);
- priv->box = temp_box;
- if (temp_extent->x1 >= 0 && temp_extent->x2 <= pixmap_width
- && temp_extent->y1 >= 0 && temp_extent->y2 <= pixmap_height) {
- int dx, dy;
- copy_box.x1 = 0;
- copy_box.y1 = 0;
- copy_box.x2 = temp_extent->x2 - temp_extent->x1;
- copy_box.y2 = temp_extent->y2 - temp_extent->y1;
- dx = temp_extent->x1;
- dy = temp_extent->y1;
- glamor_copy_n_to_n(&priv->base.pixmap->drawable,
- &temp_pixmap->drawable,
- NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL);
- // glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width,
- // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00);
- }
- else {
- for (i = 0; i < *n_regions; i++) {
- BoxPtr box;
- int nbox;
- box = REGION_RECTS(clipped_regions[i].region);
- nbox = REGION_NUM_RECTS(clipped_regions[i].region);
- while (nbox--) {
- int dx, dy, c, d;
- DEBUGF("box x1 %d y1 %d x2 %d y2 %d \n",
- box->x1, box->y1, box->x2, box->y2);
- modulus(box->x1, pixmap_width, c);
- dx = c - (box->x1 - temp_box.x1);
- copy_box.x1 = box->x1 - temp_box.x1;
- copy_box.x2 = box->x2 - temp_box.x1;
- modulus(box->y1, pixmap_height, d);
- dy = d - (box->y1 - temp_box.y1);
- copy_box.y1 = box->y1 - temp_box.y1;
- copy_box.y2 = box->y2 - temp_box.y1;
- DEBUGF("copying box %d %d %d %d, dx %d dy %d\n",
- copy_box.x1, copy_box.y1, copy_box.x2,
- copy_box.y2, dx, dy);
- glamor_copy_n_to_n(&priv->base.pixmap->drawable,
- &temp_pixmap->drawable,
- NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL);
- box++;
- }
- }
- //glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width,
- // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff);
- }
- /* The first region will be released at caller side. */
- for (i = 1; i < *n_regions; i++)
- RegionDestroy(clipped_regions[i].region);
- RegionDestroy(temp_region);
- priv->box = temp_box;
- priv->base.fbo = glamor_pixmap_detach_fbo(temp_priv);
- DEBUGF("priv box x1 %d y1 %d x2 %d y2 %d \n",
- priv->box.x1, priv->box.y1, priv->box.x2, priv->box.y2);
- glamor_destroy_pixmap(temp_pixmap);
- *need_clean_fbo = 1;
- *n_regions = 1;
- }
- /**
- * Given an expected transformed block width and block height,
- *
- * This function calculate a new block width and height which
- * guarantee the transform result will not exceed the given
- * block width and height.
- *
- * For large block width and height (> 2048), we choose a
- * smaller new width and height and to reduce the cross region
- * boundary and can avoid some overhead.
- *
- **/
- Bool
- glamor_get_transform_block_size(struct pixman_transform *transform,
- int block_w, int block_h,
- int *transformed_block_w,
- int *transformed_block_h)
- {
- double a, b, c, d, e, f, g, h;
- double scale;
- int width, height;
- a = pixman_fixed_to_double(transform->matrix[0][0]);
- b = pixman_fixed_to_double(transform->matrix[0][1]);
- c = pixman_fixed_to_double(transform->matrix[1][0]);
- d = pixman_fixed_to_double(transform->matrix[1][1]);
- scale = pixman_fixed_to_double(transform->matrix[2][2]);
- if (block_w > 2048) {
- /* For large block size, we shrink it to smaller box,
- * thus latter we may get less cross boundary regions and
- * thus can avoid some extra copy.
- *
- **/
- width = block_w / 4;
- height = block_h / 4;
- }
- else {
- width = block_w - 2;
- height = block_h - 2;
- }
- e = a + b;
- f = c + d;
- g = a - b;
- h = c - d;
- e = MIN(block_w, floor(width * scale) / MAX(fabs(e), fabs(g)));
- f = MIN(block_h, floor(height * scale) / MAX(fabs(f), fabs(h)));
- *transformed_block_w = MIN(e, f) - 1;
- *transformed_block_h = *transformed_block_w;
- if (*transformed_block_w <= 0 || *transformed_block_h <= 0)
- return FALSE;
- DEBUGF("original block_w/h %d %d, fixed %d %d \n", block_w, block_h,
- *transformed_block_w, *transformed_block_h);
- return TRUE;
- }
- #define VECTOR_FROM_POINT(p, x, y) \
- p.v[0] = x; \
- p.v[1] = y; \
- p.v[2] = 1.0;
- void
- glamor_get_transform_extent_from_box(struct pixman_box32 *box,
- struct pixman_transform *transform)
- {
- struct pixman_f_vector p0, p1, p2, p3;
- float min_x, min_y, max_x, max_y;
- struct pixman_f_transform ftransform;
- VECTOR_FROM_POINT(p0, box->x1, box->y1)
- VECTOR_FROM_POINT(p1, box->x2, box->y1)
- VECTOR_FROM_POINT(p2, box->x2, box->y2)
- VECTOR_FROM_POINT(p3, box->x1, box->y2)
- pixman_f_transform_from_pixman_transform(&ftransform, transform);
- pixman_f_transform_point(&ftransform, &p0);
- pixman_f_transform_point(&ftransform, &p1);
- pixman_f_transform_point(&ftransform, &p2);
- pixman_f_transform_point(&ftransform, &p3);
- min_x = MIN(p0.v[0], p1.v[0]);
- min_x = MIN(min_x, p2.v[0]);
- min_x = MIN(min_x, p3.v[0]);
- min_y = MIN(p0.v[1], p1.v[1]);
- min_y = MIN(min_y, p2.v[1]);
- min_y = MIN(min_y, p3.v[1]);
- max_x = MAX(p0.v[0], p1.v[0]);
- max_x = MAX(max_x, p2.v[0]);
- max_x = MAX(max_x, p3.v[0]);
- max_y = MAX(p0.v[1], p1.v[1]);
- max_y = MAX(max_y, p2.v[1]);
- max_y = MAX(max_y, p3.v[1]);
- box->x1 = floor(min_x) - 1;
- box->y1 = floor(min_y) - 1;
- box->x2 = ceil(max_x) + 1;
- box->y2 = ceil(max_y) + 1;
- }
- static void
- _glamor_process_transformed_clipped_region(glamor_pixmap_private *priv,
- int repeat_type,
- glamor_pixmap_clipped_regions *
- clipped_regions, int *n_regions,
- int *need_clean_fbo)
- {
- int shift_x, shift_y;
- if (*n_regions != 1) {
- /* Merge all source regions into one region. */
- glamor_merge_clipped_regions(priv, repeat_type,
- clipped_regions, n_regions,
- need_clean_fbo);
- }
- else {
- SET_PIXMAP_FBO_CURRENT(priv, clipped_regions[0].block_idx);
- if (repeat_type == RepeatReflect || repeat_type == RepeatNormal) {
- /* The required source areas are in one region,
- * we need to shift the corresponding box's coords to proper position,
- * thus we can calculate the relative coords correctly.*/
- BoxPtr temp_box;
- int rem;
- temp_box = RegionExtents(clipped_regions[0].region);
- modulus(temp_box->x1, priv->base.pixmap->drawable.width, rem);
- shift_x = (temp_box->x1 - rem) / priv->base.pixmap->drawable.width;
- modulus(temp_box->y1, priv->base.pixmap->drawable.height, rem);
- shift_y = (temp_box->y1 - rem) / priv->base.pixmap->drawable.height;
- if (shift_x != 0) {
- priv->large.box.x1 +=
- shift_x * priv->base.pixmap->drawable.width;
- priv->large.box.x2 +=
- shift_x * priv->base.pixmap->drawable.width;
- }
- if (shift_y != 0) {
- priv->large.box.y1 +=
- shift_y * priv->base.pixmap->drawable.height;
- priv->large.box.y2 +=
- shift_y * priv->base.pixmap->drawable.height;
- }
- }
- }
- }
- Bool
- glamor_composite_largepixmap_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, Bool force_clip,
- INT16 x_source,
- INT16 y_source,
- INT16 x_mask,
- INT16 y_mask,
- INT16 x_dest, INT16 y_dest,
- CARD16 width, CARD16 height)
- {
- glamor_pixmap_clipped_regions *clipped_dest_regions;
- glamor_pixmap_clipped_regions *clipped_source_regions;
- glamor_pixmap_clipped_regions *clipped_mask_regions;
- int n_dest_regions;
- int n_mask_regions;
- int n_source_regions;
- int i, j, k;
- int need_clean_source_fbo = 0;
- int need_clean_mask_fbo = 0;
- int is_normal_source_fbo = 0;
- int is_normal_mask_fbo = 0;
- int fixed_block_width, fixed_block_height;
- int null_source, null_mask;
- glamor_pixmap_private *need_free_source_pixmap_priv = NULL;
- glamor_pixmap_private *need_free_mask_pixmap_priv = NULL;
- int source_repeat_type = 0, mask_repeat_type = 0;
- int ok = TRUE;
- if (source->repeat)
- source_repeat_type = source->repeatType;
- else
- source_repeat_type = RepeatNone;
- if (mask && mask->repeat)
- mask_repeat_type = mask->repeatType;
- else
- mask_repeat_type = RepeatNone;
- fixed_block_width = dest_pixmap_priv->large.block_w;
- fixed_block_height = dest_pixmap_priv->large.block_h;
- /* If we got an totally out-of-box region for a source or mask
- * region without repeat, we need to set it as null_source and
- * give it a solid color (0,0,0,0). */
- null_source = 0;
- null_mask = 0;
- RegionTranslate(region, -dest->pDrawable->x, -dest->pDrawable->y);
- /* need to transform the dest region to the correct sourcei/mask region.
- * it's a little complex, as one single edge of the
- * target region may be transformed to cross a block boundary of the
- * source or mask. Then it's impossible to handle it as usual way.
- * We may have to split the original dest region to smaller region, and
- * make sure each region's transformed region can fit into one texture,
- * and then continue this loop again, and each time when a transformed region
- * cross the bound, we need to copy it to a single pixmap and do the composition
- * with the new pixmap. If the transformed region doesn't cross a source/mask's
- * boundary then we don't need to copy.
- *
- */
- if (source_pixmap_priv
- && source->transform
- && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
- int source_transformed_block_width, source_transformed_block_height;
- if (!glamor_get_transform_block_size(source->transform,
- source_pixmap_priv->large.block_w,
- source_pixmap_priv->large.block_h,
- &source_transformed_block_width,
- &source_transformed_block_height))
- {
- DEBUGF("source block size less than 1, fallback.\n");
- RegionTranslate(region, dest->pDrawable->x, dest->pDrawable->y);
- return FALSE;
- }
- fixed_block_width =
- min(fixed_block_width, source_transformed_block_width);
- fixed_block_height =
- min(fixed_block_height, source_transformed_block_height);
- DEBUGF("new source block size %d x %d \n", fixed_block_width,
- fixed_block_height);
- }
- if (mask_pixmap_priv
- && mask->transform && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
- int mask_transformed_block_width, mask_transformed_block_height;
- if (!glamor_get_transform_block_size(mask->transform,
- mask_pixmap_priv->large.block_w,
- mask_pixmap_priv->large.block_h,
- &mask_transformed_block_width,
- &mask_transformed_block_height)) {
- DEBUGF("mask block size less than 1, fallback.\n");
- RegionTranslate(region, dest->pDrawable->x, dest->pDrawable->y);
- return FALSE;
- }
- fixed_block_width =
- min(fixed_block_width, mask_transformed_block_width);
- fixed_block_height =
- min(fixed_block_height, mask_transformed_block_height);
- DEBUGF("new mask block size %d x %d \n", fixed_block_width,
- fixed_block_height);
- }
- /*compute the correct block width and height whose transformed source/mask
- *region can fit into one texture.*/
- if (force_clip || fixed_block_width < dest_pixmap_priv->large.block_w
- || fixed_block_height < dest_pixmap_priv->large.block_h)
- clipped_dest_regions =
- glamor_compute_clipped_regions_ext(dest_pixmap_priv, region,
- &n_dest_regions,
- fixed_block_width,
- fixed_block_height, 0, 0);
- else
- clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv,
- region,
- &n_dest_regions,
- 0, 0, 0);
- DEBUGF("dest clipped result %d region: \n", n_dest_regions);
- if (source_pixmap_priv
- && (source_pixmap_priv == dest_pixmap_priv ||
- source_pixmap_priv == mask_pixmap_priv)
- && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
- /* XXX self-copy... */
- need_free_source_pixmap_priv = source_pixmap_priv;
- source_pixmap_priv = malloc(sizeof(*source_pixmap_priv));
- *source_pixmap_priv = *need_free_source_pixmap_priv;
- need_free_source_pixmap_priv = source_pixmap_priv;
- }
- assert(mask_pixmap_priv != dest_pixmap_priv);
- for (i = 0; i < n_dest_regions; i++) {
- DEBUGF("dest region %d idx %d\n", i,
- clipped_dest_regions[i].block_idx);
- DEBUGRegionPrint(clipped_dest_regions[i].region);
- SET_PIXMAP_FBO_CURRENT(dest_pixmap_priv,
- clipped_dest_regions[i].block_idx);
- if (source_pixmap_priv &&
- source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
- if (!source->transform && source_repeat_type != RepeatPad) {
- RegionTranslate(clipped_dest_regions[i].region,
- x_source - x_dest, y_source - y_dest);
- clipped_source_regions =
- glamor_compute_clipped_regions(source_pixmap_priv,
- clipped_dest_regions[i].
- region, &n_source_regions,
- source_repeat_type, 0, 0);
- is_normal_source_fbo = 1;
- }
- else {
- clipped_source_regions =
- glamor_compute_transform_clipped_regions(source_pixmap_priv,
- source->transform,
- clipped_dest_regions
- [i].region,
- &n_source_regions,
- x_source - x_dest,
- y_source - y_dest,
- source_repeat_type,
- 0, 0);
- is_normal_source_fbo = 0;
- if (n_source_regions == 0) {
- /* Pad the out-of-box region to (0,0,0,0). */
- null_source = 1;
- n_source_regions = 1;
- }
- else
- _glamor_process_transformed_clipped_region
- (source_pixmap_priv, source_repeat_type,
- clipped_source_regions, &n_source_regions,
- &need_clean_source_fbo);
- }
- DEBUGF("source clipped result %d region: \n", n_source_regions);
- for (j = 0; j < n_source_regions; j++) {
- if (is_normal_source_fbo)
- SET_PIXMAP_FBO_CURRENT(source_pixmap_priv,
- clipped_source_regions[j].block_idx);
- if (mask_pixmap_priv &&
- mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
- if (is_normal_mask_fbo && is_normal_source_fbo) {
- /* both mask and source are normal fbo box without transform or repeatpad.
- * The region is clipped against source and then we clip it against mask here.*/
- DEBUGF("source region %d idx %d\n", j,
- clipped_source_regions[j].block_idx);
- DEBUGRegionPrint(clipped_source_regions[j].region);
- RegionTranslate(clipped_source_regions[j].region,
- -x_source + x_mask, -y_source + y_mask);
- clipped_mask_regions =
- glamor_compute_clipped_regions(mask_pixmap_priv,
- clipped_source_regions
- [j].region,
- &n_mask_regions,
- mask_repeat_type, 0,
- 0);
- is_normal_mask_fbo = 1;
- }
- else if (is_normal_mask_fbo && !is_normal_source_fbo) {
- assert(n_source_regions == 1);
- /* The source fbo is not a normal fbo box, it has transform or repeatpad.
- * the valid clip region should be the clip dest region rather than the
- * clip source region.*/
- RegionTranslate(clipped_dest_regions[i].region,
- -x_dest + x_mask, -y_dest + y_mask);
- clipped_mask_regions =
- glamor_compute_clipped_regions(mask_pixmap_priv,
- clipped_dest_regions
- [i].region,
- &n_mask_regions,
- mask_repeat_type, 0,
- 0);
- is_normal_mask_fbo = 1;
- }
- else {
- /* This mask region has transform or repeatpad, we need clip it agains the previous
- * valid region rather than the mask region. */
- if (!is_normal_source_fbo)
- clipped_mask_regions =
- glamor_compute_transform_clipped_regions
- (mask_pixmap_priv, mask->transform,
- clipped_dest_regions[i].region,
- &n_mask_regions, x_mask - x_dest,
- y_mask - y_dest, mask_repeat_type, 0, 0);
- else
- clipped_mask_regions =
- glamor_compute_transform_clipped_regions
- (mask_pixmap_priv, mask->transform,
- clipped_source_regions[j].region,
- &n_mask_regions, x_mask - x_source,
- y_mask - y_source, mask_repeat_type, 0, 0);
- is_normal_mask_fbo = 0;
- if (n_mask_regions == 0) {
- /* Pad the out-of-box region to (0,0,0,0). */
- null_mask = 1;
- n_mask_regions = 1;
- }
- else
- _glamor_process_transformed_clipped_region
- (mask_pixmap_priv, mask_repeat_type,
- clipped_mask_regions, &n_mask_regions,
- &need_clean_mask_fbo);
- }
- DEBUGF("mask clipped result %d region: \n", n_mask_regions);
- #define COMPOSITE_REGION(region) do { \
- if (!glamor_composite_clipped_region(op, \
- null_source ? NULL : source, \
- null_mask ? NULL : mask, dest, \
- null_source ? NULL : source_pixmap_priv, \
- null_mask ? NULL : mask_pixmap_priv, \
- dest_pixmap_priv, region, \
- x_source, y_source, x_mask, y_mask, \
- x_dest, y_dest)) { \
- assert(0); \
- } \
- } while(0)
- for (k = 0; k < n_mask_regions; k++) {
- DEBUGF("mask region %d idx %d\n", k,
- clipped_mask_regions[k].block_idx);
- DEBUGRegionPrint(clipped_mask_regions[k].region);
- if (is_normal_mask_fbo) {
- SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv,
- clipped_mask_regions[k].
- block_idx);
- DEBUGF("mask fbo off %d %d \n",
- mask_pixmap_priv->large.box.x1,
- mask_pixmap_priv->large.box.y1);
- DEBUGF("start composite mask hasn't transform.\n");
- RegionTranslate(clipped_mask_regions[k].region,
- x_dest - x_mask +
- dest->pDrawable->x,
- y_dest - y_mask +
- dest->pDrawable->y);
- COMPOSITE_REGION(clipped_mask_regions[k].region);
- }
- else if (!is_normal_mask_fbo && !is_normal_source_fbo) {
- DEBUGF
- ("start composite both mask and source have transform.\n");
- RegionTranslate(clipped_dest_regions[i].region,
- dest->pDrawable->x,
- dest->pDrawable->y);
- COMPOSITE_REGION(clipped_dest_regions[i].region);
- }
- else {
- DEBUGF
- ("start composite only mask has transform.\n");
- RegionTranslate(clipped_source_regions[j].region,
- x_dest - x_source +
- dest->pDrawable->x,
- y_dest - y_source +
- dest->pDrawable->y);
- COMPOSITE_REGION(clipped_source_regions[j].region);
- }
- RegionDestroy(clipped_mask_regions[k].region);
- }
- free(clipped_mask_regions);
- if (null_mask)
- null_mask = 0;
- if (need_clean_mask_fbo) {
- assert(is_normal_mask_fbo == 0);
- glamor_destroy_fbo(mask_pixmap_priv->base.fbo);
- mask_pixmap_priv->base.fbo = NULL;
- need_clean_mask_fbo = 0;
- }
- }
- else {
- if (is_normal_source_fbo) {
- RegionTranslate(clipped_source_regions[j].region,
- -x_source + x_dest + dest->pDrawable->x,
- -y_source + y_dest +
- dest->pDrawable->y);
- COMPOSITE_REGION(clipped_source_regions[j].region);
- }
- else {
- /* Source has transform or repeatPad. dest regions is the right
- * region to do the composite. */
- RegionTranslate(clipped_dest_regions[i].region,
- dest->pDrawable->x, dest->pDrawable->y);
- COMPOSITE_REGION(clipped_dest_regions[i].region);
- }
- }
- if (clipped_source_regions && clipped_source_regions[j].region)
- RegionDestroy(clipped_source_regions[j].region);
- }
- free(clipped_source_regions);
- if (null_source)
- null_source = 0;
- if (need_clean_source_fbo) {
- assert(is_normal_source_fbo == 0);
- glamor_destroy_fbo(source_pixmap_priv->base.fbo);
- source_pixmap_priv->base.fbo = NULL;
- need_clean_source_fbo = 0;
- }
- }
- else {
- if (mask_pixmap_priv &&
- mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
- if (!mask->transform && mask_repeat_type != RepeatPad) {
- RegionTranslate(clipped_dest_regions[i].region,
- x_mask - x_dest, y_mask - y_dest);
- clipped_mask_regions =
- glamor_compute_clipped_regions(mask_pixmap_priv,
- clipped_dest_regions[i].
- region, &n_mask_regions,
- mask_repeat_type, 0, 0);
- is_normal_mask_fbo = 1;
- }
- else {
- clipped_mask_regions =
- glamor_compute_transform_clipped_regions
- (mask_pixmap_priv, mask->transform,
- clipped_dest_regions[i].region, &n_mask_regions,
- x_mask - x_dest, y_mask - y_dest, mask_repeat_type, 0,
- 0);
- is_normal_mask_fbo = 0;
- if (n_mask_regions == 0) {
- /* Pad the out-of-box region to (0,0,0,0). */
- null_mask = 1;
- n_mask_regions = 1;
- }
- else
- _glamor_process_transformed_clipped_region
- (mask_pixmap_priv, mask_repeat_type,
- clipped_mask_regions, &n_mask_regions,
- &need_clean_mask_fbo);
- }
- for (k = 0; k < n_mask_regions; k++) {
- DEBUGF("mask region %d idx %d\n", k,
- clipped_mask_regions[k].block_idx);
- DEBUGRegionPrint(clipped_mask_regions[k].region);
- if (is_normal_mask_fbo) {
- SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv,
- clipped_mask_regions[k].
- block_idx);
- RegionTranslate(clipped_mask_regions[k].region,
- x_dest - x_mask + dest->pDrawable->x,
- y_dest - y_mask + dest->pDrawable->y);
- COMPOSITE_REGION(clipped_mask_regions[k].region);
- }
- else {
- RegionTranslate(clipped_dest_regions[i].region,
- dest->pDrawable->x, dest->pDrawable->y);
- COMPOSITE_REGION(clipped_dest_regions[i].region);
- }
- RegionDestroy(clipped_mask_regions[k].region);
- }
- free(clipped_mask_regions);
- if (null_mask)
- null_mask = 0;
- if (need_clean_mask_fbo) {
- glamor_destroy_fbo(mask_pixmap_priv->base.fbo);
- mask_pixmap_priv->base.fbo = NULL;
- need_clean_mask_fbo = 0;
- }
- }
- else {
- RegionTranslate(clipped_dest_regions[i].region,
- dest->pDrawable->x, dest->pDrawable->y);
- COMPOSITE_REGION(clipped_dest_regions[i].region);
- }
- }
- RegionDestroy(clipped_dest_regions[i].region);
- }
- free(clipped_dest_regions);
- free(need_free_source_pixmap_priv);
- free(need_free_mask_pixmap_priv);
- ok = TRUE;
- return ok;
- }
|