summaryrefslogtreecommitdiff
path: root/src/sna/fb/fbpict.c
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-11-06 21:16:29 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-11-06 21:16:29 -0800
commit1501461b978a770b6fc8883901d6c3d177661667 (patch)
tree476568764b15008dce7c60e818480d3e5432e176 /src/sna/fb/fbpict.c
downloadxf86-video-intel-1501461b978a770b6fc8883901d6c3d177661667.tar.gz
xf86-video-intel-1501461b978a770b6fc8883901d6c3d177661667.tar.bz2
xf86-video-intel-1501461b978a770b6fc8883901d6c3d177661667.zip
Imported Upstream version 2.20.10upstream/2.20.10
Diffstat (limited to 'src/sna/fb/fbpict.c')
-rw-r--r--src/sna/fb/fbpict.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/sna/fb/fbpict.c b/src/sna/fb/fbpict.c
new file mode 100644
index 000000000..a2038518e
--- /dev/null
+++ b/src/sna/fb/fbpict.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright © 2000 SuSE, Inc.
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#include <string.h>
+
+#include "fb.h"
+
+#include <picturestr.h>
+#include <mipict.h>
+#include "fbpict.h"
+
+static void
+SourceValidateOnePicture(PicturePtr picture)
+{
+ DrawablePtr drawable = picture->pDrawable;
+ ScreenPtr screen;
+
+ if (!drawable)
+ return;
+
+ screen = drawable->pScreen;
+ if (screen->SourceValidate)
+ screen->SourceValidate(drawable,
+ 0, 0, drawable->width, drawable->height,
+ picture->subWindowMode);
+}
+
+static void
+fbCompositeSourceValidate(PicturePtr picture)
+{
+ SourceValidateOnePicture(picture);
+ if (picture->alphaMap)
+ SourceValidateOnePicture(picture->alphaMap);
+}
+
+void
+fbComposite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+ pixman_image_t *src, *mask, *dest;
+ int src_xoff, src_yoff;
+ int msk_xoff, msk_yoff;
+ int dst_xoff, dst_yoff;
+
+ fbCompositeSourceValidate(pSrc);
+ if (pMask)
+ fbCompositeSourceValidate(pMask);
+
+ src = image_from_pict(pSrc, FALSE, &src_xoff, &src_yoff);
+ mask = image_from_pict(pMask, FALSE, &msk_xoff, &msk_yoff);
+ dest = image_from_pict(pDst, TRUE, &dst_xoff, &dst_yoff);
+
+ if (src && dest && !(pMask && !mask)) {
+ pixman_image_composite(op, src, mask, dest,
+ xSrc + src_xoff, ySrc + src_yoff,
+ xMask + msk_xoff, yMask + msk_yoff,
+ xDst + dst_xoff, yDst + dst_yoff, width, height);
+ }
+
+ free_pixman_pict(pSrc, src);
+ free_pixman_pict(pMask, mask);
+ free_pixman_pict(pDst, dest);
+}
+
+static pixman_image_t *
+create_solid_fill_image(PicturePtr pict)
+{
+ PictSolidFill *solid = &pict->pSourcePict->solidFill;
+ pixman_color_t color;
+ CARD32 a, r, g, b;
+
+ a = (solid->color & 0xff000000) >> 24;
+ r = (solid->color & 0x00ff0000) >> 16;
+ g = (solid->color & 0x0000ff00) >> 8;
+ b = (solid->color & 0x000000ff) >> 0;
+
+ color.alpha = (a << 8) | a;
+ color.red = (r << 8) | r;
+ color.green = (g << 8) | g;
+ color.blue = (b << 8) | b;
+
+ return pixman_image_create_solid_fill(&color);
+}
+
+static pixman_image_t *
+create_linear_gradient_image(PictGradient * gradient)
+{
+ PictLinearGradient *linear = (PictLinearGradient *) gradient;
+ pixman_point_fixed_t p1;
+ pixman_point_fixed_t p2;
+
+ p1.x = linear->p1.x;
+ p1.y = linear->p1.y;
+ p2.x = linear->p2.x;
+ p2.y = linear->p2.y;
+
+ return pixman_image_create_linear_gradient(&p1, &p2,
+ (pixman_gradient_stop_t *)
+ gradient->stops,
+ gradient->nstops);
+}
+
+static pixman_image_t *
+create_radial_gradient_image(PictGradient * gradient)
+{
+ PictRadialGradient *radial = (PictRadialGradient *) gradient;
+ pixman_point_fixed_t c1;
+ pixman_point_fixed_t c2;
+
+ c1.x = radial->c1.x;
+ c1.y = radial->c1.y;
+ c2.x = radial->c2.x;
+ c2.y = radial->c2.y;
+
+ return pixman_image_create_radial_gradient(&c1, &c2, radial->c1.radius,
+ radial->c2.radius,
+ (pixman_gradient_stop_t *)
+ gradient->stops,
+ gradient->nstops);
+}
+
+static pixman_image_t *
+create_conical_gradient_image(PictGradient * gradient)
+{
+ PictConicalGradient *conical = (PictConicalGradient *) gradient;
+ pixman_point_fixed_t center;
+
+ center.x = conical->center.x;
+ center.y = conical->center.y;
+
+ return pixman_image_create_conical_gradient(&center, conical->angle,
+ (pixman_gradient_stop_t *)
+ gradient->stops,
+ gradient->nstops);
+}
+
+static pixman_image_t *
+create_bits_picture(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+{
+ PixmapPtr pixmap;
+ FbBits *bits;
+ FbStride stride;
+ int bpp;
+ pixman_image_t *image;
+
+ fbGetDrawablePixmap(pict->pDrawable, pixmap, *xoff, *yoff);
+ fbGetPixmapBitsData(pixmap, bits, stride, bpp);
+
+ image = pixman_image_create_bits((pixman_format_code_t) pict->format,
+ pixmap->drawable.width,
+ pixmap->drawable.height, (uint32_t *) bits,
+ stride * sizeof(FbStride));
+
+ if (!image)
+ return NULL;
+
+ /* pCompositeClip is undefined for source pictures, so
+ * only set the clip region for pictures with drawables
+ */
+ if (has_clip) {
+ if (pict->clientClipType != CT_NONE)
+ pixman_image_set_has_client_clip(image, TRUE);
+
+ if (*xoff || *yoff)
+ pixman_region_translate(pict->pCompositeClip, *xoff, *yoff);
+
+ pixman_image_set_clip_region(image, pict->pCompositeClip);
+
+ if (*xoff || *yoff)
+ pixman_region_translate(pict->pCompositeClip, -*xoff, -*yoff);
+ }
+
+ /* Indexed table */
+ if (pict->pFormat->index.devPrivate)
+ pixman_image_set_indexed(image, pict->pFormat->index.devPrivate);
+
+ /* Add in drawable origin to position within the image */
+ *xoff += pict->pDrawable->x;
+ *yoff += pict->pDrawable->y;
+
+ return image;
+}
+
+static pixman_image_t *image_from_pict_internal(PicturePtr pict, Bool has_clip,
+ int *xoff, int *yoff,
+ Bool is_alpha_map);
+
+static void
+set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip,
+ int *xoff, int *yoff, Bool is_alpha_map)
+{
+ pixman_repeat_t repeat;
+ pixman_filter_t filter;
+
+ if (pict->transform) {
+ /* For source images, adjust the transform to account
+ * for the drawable offset within the pixman image,
+ * then set the offset to 0 as it will be used
+ * to compute positions within the transformed image.
+ */
+ if (!has_clip) {
+ struct pixman_transform adjusted;
+
+ adjusted = *pict->transform;
+ pixman_transform_translate(&adjusted,
+ NULL,
+ pixman_int_to_fixed(*xoff),
+ pixman_int_to_fixed(*yoff));
+ pixman_image_set_transform(image, &adjusted);
+ *xoff = 0;
+ *yoff = 0;
+ }
+ else
+ pixman_image_set_transform(image, pict->transform);
+ }
+
+ switch (pict->repeatType) {
+ default:
+ case RepeatNone:
+ repeat = PIXMAN_REPEAT_NONE;
+ break;
+
+ case RepeatPad:
+ repeat = PIXMAN_REPEAT_PAD;
+ break;
+
+ case RepeatNormal:
+ repeat = PIXMAN_REPEAT_NORMAL;
+ break;
+
+ case RepeatReflect:
+ repeat = PIXMAN_REPEAT_REFLECT;
+ break;
+ }
+
+ pixman_image_set_repeat(image, repeat);
+
+ /* Fetch alpha map unless 'pict' is being used
+ * as the alpha map for this operation
+ */
+ if (pict->alphaMap && !is_alpha_map) {
+ int alpha_xoff, alpha_yoff;
+ pixman_image_t *alpha_map =
+ image_from_pict_internal(pict->alphaMap, FALSE, &alpha_xoff,
+ &alpha_yoff, TRUE);
+
+ pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x,
+ pict->alphaOrigin.y);
+
+ free_pixman_pict(pict->alphaMap, alpha_map);
+ }
+
+ pixman_image_set_component_alpha(image, pict->componentAlpha);
+
+ switch (pict->filter) {
+ default:
+ case PictFilterNearest:
+ case PictFilterFast:
+ filter = PIXMAN_FILTER_NEAREST;
+ break;
+
+ case PictFilterBilinear:
+ case PictFilterGood:
+ filter = PIXMAN_FILTER_BILINEAR;
+ break;
+
+ case PictFilterConvolution:
+ filter = PIXMAN_FILTER_CONVOLUTION;
+ break;
+ }
+
+ pixman_image_set_filter(image, filter,
+ (pixman_fixed_t *) pict->filter_params,
+ pict->filter_nparams);
+ pixman_image_set_source_clipping(image, TRUE);
+}
+
+static pixman_image_t *
+image_from_pict_internal(PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
+ Bool is_alpha_map)
+{
+ pixman_image_t *image = NULL;
+
+ if (!pict)
+ return NULL;
+
+ if (pict->pDrawable) {
+ image = create_bits_picture(pict, has_clip, xoff, yoff);
+ }
+ else if (pict->pSourcePict) {
+ SourcePict *sp = pict->pSourcePict;
+
+ if (sp->type == SourcePictTypeSolidFill) {
+ image = create_solid_fill_image(pict);
+ }
+ else {
+ PictGradient *gradient = &pict->pSourcePict->gradient;
+
+ if (sp->type == SourcePictTypeLinear)
+ image = create_linear_gradient_image(gradient);
+ else if (sp->type == SourcePictTypeRadial)
+ image = create_radial_gradient_image(gradient);
+ else if (sp->type == SourcePictTypeConical)
+ image = create_conical_gradient_image(gradient);
+ }
+ *xoff = *yoff = 0;
+ }
+
+ if (image)
+ set_image_properties(image, pict, has_clip, xoff, yoff, is_alpha_map);
+
+ return image;
+}
+
+pixman_image_t *
+image_from_pict(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+{
+ return image_from_pict_internal(pict, has_clip, xoff, yoff, FALSE);
+}
+
+void
+free_pixman_pict(PicturePtr pict, pixman_image_t * image)
+{
+ if (image)
+ pixman_image_unref(image);
+}