123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- /*
- *
- * Copyright © 2000 SuSE, Inc.
- * Copyright © 2007 Red Hat, Inc.
- *
- * 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.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <string.h>
- #include "fb.h"
- #include "picturestr.h"
- #include "mipict.h"
- #include "fbpict.h"
- 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;
- miCompositeSourceValidate(pSrc);
- if (pMask)
- miCompositeSourceValidate(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_glyph_cache_t *glyphCache;
- void
- fbDestroyGlyphCache(void)
- {
- if (glyphCache)
- {
- pixman_glyph_cache_destroy (glyphCache);
- glyphCache = NULL;
- }
- }
- void
- fbUnrealizeGlyph(ScreenPtr pScreen,
- GlyphPtr pGlyph)
- {
- if (glyphCache)
- pixman_glyph_cache_remove (glyphCache, pGlyph, NULL);
- }
- void
- fbGlyphs(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc, int nlist,
- GlyphListPtr list,
- GlyphPtr *glyphs)
- {
- #define N_STACK_GLYPHS 512
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
- pixman_glyph_t *pglyphs = stack_glyphs;
- pixman_image_t *srcImage, *dstImage;
- int srcXoff, srcYoff, dstXoff, dstYoff;
- GlyphPtr glyph;
- int n_glyphs;
- int x, y;
- int i, n;
- int xDst = list->xOff, yDst = list->yOff;
- miCompositeSourceValidate(pSrc);
-
- n_glyphs = 0;
- for (i = 0; i < nlist; ++i)
- n_glyphs += list[i].len;
- if (!glyphCache)
- glyphCache = pixman_glyph_cache_create();
- pixman_glyph_cache_freeze (glyphCache);
-
- if (n_glyphs > N_STACK_GLYPHS) {
- if (!(pglyphs = malloc (n_glyphs * sizeof (pixman_glyph_t))))
- goto out;
- }
-
- i = 0;
- x = y = 0;
- while (nlist--) {
- x += list->xOff;
- y += list->yOff;
- n = list->len;
- while (n--) {
- const void *g;
- glyph = *glyphs++;
- if (!(g = pixman_glyph_cache_lookup (glyphCache, glyph, NULL))) {
- pixman_image_t *glyphImage;
- PicturePtr pPicture;
- int xoff, yoff;
- pPicture = GetGlyphPicture(glyph, pScreen);
- if (!pPicture) {
- n_glyphs--;
- goto next;
- }
- if (!(glyphImage = image_from_pict(pPicture, FALSE, &xoff, &yoff)))
- goto out;
- g = pixman_glyph_cache_insert(glyphCache, glyph, NULL,
- glyph->info.x,
- glyph->info.y,
- glyphImage);
- free_pixman_pict(pPicture, glyphImage);
- if (!g)
- goto out;
- }
- pglyphs[i].x = x;
- pglyphs[i].y = y;
- pglyphs[i].glyph = g;
- i++;
- next:
- x += glyph->info.xOff;
- y += glyph->info.yOff;
- }
- list++;
- }
- if (!(srcImage = image_from_pict(pSrc, FALSE, &srcXoff, &srcYoff)))
- goto out;
- if (!(dstImage = image_from_pict(pDst, TRUE, &dstXoff, &dstYoff)))
- goto out_free_src;
- if (maskFormat) {
- pixman_format_code_t format;
- pixman_box32_t extents;
- format = maskFormat->format | (maskFormat->depth << 24);
- pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents);
- pixman_composite_glyphs(op, srcImage, dstImage, format,
- xSrc + srcXoff + extents.x1 - xDst, ySrc + srcYoff + extents.y1 - yDst,
- extents.x1, extents.y1,
- extents.x1 + dstXoff, extents.y1 + dstYoff,
- extents.x2 - extents.x1,
- extents.y2 - extents.y1,
- glyphCache, n_glyphs, pglyphs);
- }
- else {
- pixman_composite_glyphs_no_mask(op, srcImage, dstImage,
- xSrc + srcXoff - xDst, ySrc + srcYoff - yDst,
- dstXoff, dstYoff,
- glyphCache, n_glyphs, pglyphs);
- }
- free_pixman_pict(pDst, dstImage);
- out_free_src:
- free_pixman_pict(pSrc, srcImage);
- out:
- pixman_glyph_cache_thaw(glyphCache);
- if (pglyphs != stack_glyphs)
- free(pglyphs);
- }
- 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(¢er, 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;
- #ifdef FB_ACCESS_WRAPPER
- #if FB_SHIFT==5
- pixman_image_set_accessors(image,
- (pixman_read_memory_func_t) wfbReadMemory,
- (pixman_write_memory_func_t) wfbWriteMemory);
- #else
- #error The pixman library only works when FbBits is 32 bits wide
- #endif
- #endif
- /* 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) && pict->pDrawable)
- fbFinishAccess(pict->pDrawable);
- }
- Bool
- fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
- {
- PictureScreenPtr ps;
- if (!miPictureInit(pScreen, formats, nformats))
- return FALSE;
- ps = GetPictureScreen(pScreen);
- ps->Composite = fbComposite;
- ps->Glyphs = fbGlyphs;
- ps->UnrealizeGlyph = fbUnrealizeGlyph;
- ps->CompositeRects = miCompositeRects;
- ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
- ps->Trapezoids = fbTrapezoids;
- ps->AddTraps = fbAddTraps;
- ps->AddTriangles = fbAddTriangles;
- ps->Triangles = fbTriangles;
- return TRUE;
- }
|