diff options
Diffstat (limited to 'xorg-server/glamor/glamor_compositerects.c')
-rw-r--r-- | xorg-server/glamor/glamor_compositerects.c | 458 |
1 files changed, 228 insertions, 230 deletions
diff --git a/xorg-server/glamor/glamor_compositerects.c b/xorg-server/glamor/glamor_compositerects.c index 1a5769958..3b6b2ed07 100644 --- a/xorg-server/glamor/glamor_compositerects.c +++ b/xorg-server/glamor/glamor_compositerects.c @@ -36,243 +36,241 @@ * compositeRects acceleration implementation */ -static int16_t bound(int16_t a, uint16_t b) +static int16_t +bound(int16_t a, uint16_t b) { - int v = (int)a + (int)b; - if (v > MAXSHORT) - return MAXSHORT; - return v; + int v = (int) a + (int) b; + + if (v > MAXSHORT) + return MAXSHORT; + return v; } static Bool -_pixman_region_init_clipped_rectangles(pixman_region16_t *region, - unsigned int num_rects, - xRectangle *rects, - int tx, int ty, - BoxPtr extents) +_pixman_region_init_clipped_rectangles(pixman_region16_t * region, + unsigned int num_rects, + xRectangle *rects, + int tx, int ty, BoxPtr extents) { - pixman_box16_t stack_boxes[64], *boxes = stack_boxes; - pixman_bool_t ret; - unsigned int i, j; - - if (num_rects > ARRAY_SIZE(stack_boxes)) { - boxes = malloc(sizeof(pixman_box16_t) * num_rects); - if (boxes == NULL) - return FALSE; - } - - for (i = j = 0; i < num_rects; i++) { - boxes[j].x1 = rects[i].x + tx; - if (boxes[j].x1 < extents->x1) - boxes[j].x1 = extents->x1; - - boxes[j].y1 = rects[i].y + ty; - if (boxes[j].y1 < extents->y1) - boxes[j].y1 = extents->y1; - - boxes[j].x2 = bound(rects[i].x + tx, rects[i].width); - if (boxes[j].x2 > extents->x2) - boxes[j].x2 = extents->x2; - - boxes[j].y2 = bound(rects[i].y + ty, rects[i].height); - if (boxes[j].y2 > extents->y2) - boxes[j].y2 = extents->y2; - - if (boxes[j].x2 > boxes[j].x1 && boxes[j].y2 > boxes[j].y1) - j++; - } - - ret = FALSE; - if (j) - ret = pixman_region_init_rects(region, boxes, j); - - if (boxes != stack_boxes) - free(boxes); - - DEBUGF("%s: nrects=%d, region=(%d, %d), (%d, %d) x %d\n", - __FUNCTION__, num_rects, - region->extents.x1, region->extents.y1, - region->extents.x2, region->extents.y2, - j); - return ret; + pixman_box16_t stack_boxes[64], *boxes = stack_boxes; + pixman_bool_t ret; + unsigned int i, j; + + if (num_rects > ARRAY_SIZE(stack_boxes)) { + boxes = malloc(sizeof(pixman_box16_t) * num_rects); + if (boxes == NULL) + return FALSE; + } + + for (i = j = 0; i < num_rects; i++) { + boxes[j].x1 = rects[i].x + tx; + if (boxes[j].x1 < extents->x1) + boxes[j].x1 = extents->x1; + + boxes[j].y1 = rects[i].y + ty; + if (boxes[j].y1 < extents->y1) + boxes[j].y1 = extents->y1; + + boxes[j].x2 = bound(rects[i].x + tx, rects[i].width); + if (boxes[j].x2 > extents->x2) + boxes[j].x2 = extents->x2; + + boxes[j].y2 = bound(rects[i].y + ty, rects[i].height); + if (boxes[j].y2 > extents->y2) + boxes[j].y2 = extents->y2; + + if (boxes[j].x2 > boxes[j].x1 && boxes[j].y2 > boxes[j].y1) + j++; + } + + ret = FALSE; + if (j) + ret = pixman_region_init_rects(region, boxes, j); + + if (boxes != stack_boxes) + free(boxes); + + DEBUGF("%s: nrects=%d, region=(%d, %d), (%d, %d) x %d\n", + __FUNCTION__, num_rects, + region->extents.x1, region->extents.y1, + region->extents.x2, region->extents.y2, j); + return ret; } - void -glamor_composite_rectangles(CARD8 op, - PicturePtr dst, - xRenderColor *color, - int num_rects, - xRectangle *rects) +glamor_composite_rectangles(CARD8 op, + PicturePtr dst, + xRenderColor * color, + int num_rects, xRectangle *rects) { - PixmapPtr pixmap; - struct glamor_pixmap_private *priv; - pixman_region16_t region; - pixman_box16_t *boxes; - int dst_x, dst_y; - int num_boxes; - PicturePtr source = NULL; - Bool need_free_region = FALSE; - - DEBUGF("%s(op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n", - __FUNCTION__, op, - (color->alpha >> 8 << 24) | - (color->red >> 8 << 16) | - (color->green >> 8 << 8) | - (color->blue >> 8 << 0), - num_rects, - rects[0].x, rects[0].y, rects[0].width, rects[0].height); - - if (!num_rects) - return; - - if (region_is_empty(dst->pCompositeClip)) { - DEBUGF("%s: empty clip, skipping\n", __FUNCTION__); - return; - } - - if ((color->red|color->green|color->blue|color->alpha) <= 0x00ff) { - switch (op) { - case PictOpOver: - case PictOpOutReverse: - case PictOpAdd: - return; - case PictOpInReverse: - case PictOpSrc: - op = PictOpClear; - break; - case PictOpAtopReverse: - op = PictOpOut; - break; - case PictOpXor: - op = PictOpOverReverse; - break; - } - } - if (color->alpha <= 0x00ff) { - switch (op) { - case PictOpOver: - case PictOpOutReverse: - return; - case PictOpInReverse: - op = PictOpClear; - break; - case PictOpAtopReverse: - op = PictOpOut; - break; - case PictOpXor: - op = PictOpOverReverse; - break; - } - } else if (color->alpha >= 0xff00) { - switch (op) { - case PictOpOver: - op = PictOpSrc; - break; - case PictOpInReverse: - return; - case PictOpOutReverse: - op = PictOpClear; - break; - case PictOpAtopReverse: - op = PictOpOverReverse; - break; - case PictOpXor: - op = PictOpOut; - break; - } - } - DEBUGF("%s: converted to op %d\n", __FUNCTION__, op); - - if (!_pixman_region_init_clipped_rectangles(®ion, - num_rects, rects, - dst->pDrawable->x, - dst->pDrawable->y, - &dst->pCompositeClip->extents)) - { - DEBUGF("%s: allocation failed for region\n", __FUNCTION__); - return; - } - - pixmap = glamor_get_drawable_pixmap(dst->pDrawable); - priv = glamor_get_pixmap_private(pixmap); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) - goto fallback; - if (dst->alphaMap) { - DEBUGF("%s: fallback, dst has an alpha-map\n", __FUNCTION__); - goto fallback; - } - - need_free_region = TRUE; - - DEBUGF("%s: drawable extents (%d, %d),(%d, %d) x %d\n", - __FUNCTION__, - RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, - RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, - RegionNumRects(®ion)); - - if (dst->pCompositeClip->data && - (!pixman_region_intersect(®ion, ®ion, dst->pCompositeClip) || - region_is_empty(®ion))) { - DEBUGF("%s: zero-intersection between rectangles and clip\n", - __FUNCTION__); - pixman_region_fini(®ion); - return; - } - - DEBUGF("%s: clipped extents (%d, %d),(%d, %d) x %d\n", - __FUNCTION__, - RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, - RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, - RegionNumRects(®ion)); - - glamor_get_drawable_deltas(dst->pDrawable, pixmap, &dst_x, &dst_y); - pixman_region_translate(®ion, dst_x, dst_y); - - DEBUGF("%s: pixmap +(%d, %d) extents (%d, %d),(%d, %d)\n", - __FUNCTION__, dst_x, dst_y, - RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, - RegionExtents(®ion)->x2, RegionExtents(®ion)->y2); - - - boxes = pixman_region_rectangles(®ion, &num_boxes); - if (op == PictOpSrc || op == PictOpClear) { - CARD32 pixel; - if (op == PictOpClear) - pixel = 0; - else - miRenderColorToPixel(dst->pFormat, color, &pixel); - glamor_solid_boxes(pixmap, boxes, num_boxes, pixel); - - goto done; - } else { - if (likely(priv->type != GLAMOR_TEXTURE_LARGE)) { - int error; - - source = CreateSolidPicture(0, color, &error); - if (!source) - goto done; - if (glamor_composite_clipped_region(op, source, - NULL, dst, - NULL, NULL, priv, - ®ion, - 0,0,0,0,0,0)) - goto done; - } - } -fallback: - miCompositeRects(op, dst, color, num_rects, rects); -done: - /* XXX xserver-1.8: CompositeRects is not tracked by Damage, so we must - * manually append the damaged regions ourselves. - */ - DamageRegionAppend(&pixmap->drawable, ®ion); - DamageRegionProcessPending(&pixmap->drawable); - - if (need_free_region) - pixman_region_fini(®ion); - if (source) - FreePicture(source, 0); - return; + PixmapPtr pixmap; + struct glamor_pixmap_private *priv; + pixman_region16_t region; + pixman_box16_t *boxes; + int dst_x, dst_y; + int num_boxes; + PicturePtr source = NULL; + Bool need_free_region = FALSE; + + DEBUGF("%s(op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n", + __FUNCTION__, op, + (color->alpha >> 8 << 24) | + (color->red >> 8 << 16) | + (color->green >> 8 << 8) | + (color->blue >> 8 << 0), + num_rects, rects[0].x, rects[0].y, rects[0].width, rects[0].height); + + if (!num_rects) + return; + + if (RegionNil(dst->pCompositeClip)) { + DEBUGF("%s: empty clip, skipping\n", __FUNCTION__); + return; + } + + if ((color->red | color->green | color->blue | color->alpha) <= 0x00ff) { + switch (op) { + case PictOpOver: + case PictOpOutReverse: + case PictOpAdd: + return; + case PictOpInReverse: + case PictOpSrc: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOut; + break; + case PictOpXor: + op = PictOpOverReverse; + break; + } + } + if (color->alpha <= 0x00ff) { + switch (op) { + case PictOpOver: + case PictOpOutReverse: + return; + case PictOpInReverse: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOut; + break; + case PictOpXor: + op = PictOpOverReverse; + break; + } + } + else if (color->alpha >= 0xff00) { + switch (op) { + case PictOpOver: + op = PictOpSrc; + break; + case PictOpInReverse: + return; + case PictOpOutReverse: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOverReverse; + break; + case PictOpXor: + op = PictOpOut; + break; + } + } + DEBUGF("%s: converted to op %d\n", __FUNCTION__, op); + + if (!_pixman_region_init_clipped_rectangles(®ion, + num_rects, rects, + dst->pDrawable->x, + dst->pDrawable->y, + &dst->pCompositeClip->extents)) + { + DEBUGF("%s: allocation failed for region\n", __FUNCTION__); + return; + } + + pixmap = glamor_get_drawable_pixmap(dst->pDrawable); + priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) + goto fallback; + if (dst->alphaMap) { + DEBUGF("%s: fallback, dst has an alpha-map\n", __FUNCTION__); + goto fallback; + } + + need_free_region = TRUE; + + DEBUGF("%s: drawable extents (%d, %d),(%d, %d) x %d\n", + __FUNCTION__, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, + RegionNumRects(®ion)); + + if (dst->pCompositeClip->data && + (!pixman_region_intersect(®ion, ®ion, dst->pCompositeClip) || + RegionNil(®ion))) { + DEBUGF("%s: zero-intersection between rectangles and clip\n", + __FUNCTION__); + pixman_region_fini(®ion); + return; + } + + DEBUGF("%s: clipped extents (%d, %d),(%d, %d) x %d\n", + __FUNCTION__, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, + RegionNumRects(®ion)); + + glamor_get_drawable_deltas(dst->pDrawable, pixmap, &dst_x, &dst_y); + pixman_region_translate(®ion, dst_x, dst_y); + + DEBUGF("%s: pixmap +(%d, %d) extents (%d, %d),(%d, %d)\n", + __FUNCTION__, dst_x, dst_y, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2); + + boxes = pixman_region_rectangles(®ion, &num_boxes); + if (op == PictOpSrc || op == PictOpClear) { + CARD32 pixel; + + if (op == PictOpClear) + pixel = 0; + else + miRenderColorToPixel(dst->pFormat, color, &pixel); + glamor_solid_boxes(pixmap, boxes, num_boxes, pixel); + + goto done; + } + else { + if (_X_LIKELY(priv->type != GLAMOR_TEXTURE_LARGE)) { + int error; + + source = CreateSolidPicture(0, color, &error); + if (!source) + goto done; + if (glamor_composite_clipped_region(op, source, + NULL, dst, + NULL, NULL, priv, + ®ion, 0, 0, 0, 0, 0, 0)) + goto done; + } + } + fallback: + miCompositeRects(op, dst, color, num_rects, rects); + done: + /* XXX xserver-1.8: CompositeRects is not tracked by Damage, so we must + * manually append the damaged regions ourselves. + */ + DamageRegionAppend(&pixmap->drawable, ®ion); + DamageRegionProcessPending(&pixmap->drawable); + + if (need_free_region) + pixman_region_fini(®ion); + if (source) + FreePicture(source, 0); + return; } |