123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- /*
- * 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:
- * Zhigang Gong <zhigang.gong@linux.intel.com>
- *
- * original author is Chris Wilson at sna.
- *
- */
- #include "glamor_priv.h"
- #include "mipict.h"
- #include "damage.h"
- /** @file glamor_compositerects.
- *
- * compositeRects acceleration implementation
- */
- static int16_t
- bound(int16_t a, uint16_t b)
- {
- 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_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)
- {
- 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;
- }
|