#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;
miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height);
if (pMask)
miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height);
src = image_from_pict (pSrc, TRUE);
mask = image_from_pict (pMask, TRUE);
dest = image_from_pict (pDst, TRUE);
if (src && dest && !(pMask && !mask))
{
pixman_image_composite (op, src, mask, dest,
xSrc, ySrc, xMask, yMask, xDst, yDst,
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 (
¢er, conical->angle, (pixman_gradient_stop_t *)gradient->stops,
gradient->nstops);
}
static pixman_image_t *
create_bits_picture (PicturePtr pict,
Bool has_clip)
{
FbBits *bits;
FbStride stride;
int bpp, xoff, yoff;
pixman_image_t *image;
fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
bits = (FbBits*)((CARD8*)bits +
(pict->pDrawable->y + yoff) * stride * sizeof(FbBits) +
(pict->pDrawable->x + xoff) * (bpp / 8));
image = pixman_image_create_bits (
pict->format,
pict->pDrawable->width, pict->pDrawable->height,
(uint32_t *)bits, stride * sizeof (FbStride));
#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
if (has_clip)
{
if (pict->clientClipType != CT_NONE)
pixman_image_set_has_client_clip (image, TRUE);
pixman_region_translate (pict->pCompositeClip, - pict->pDrawable->x, - pict->pDrawable->y);
pixman_image_set_clip_region (image, pict->pCompositeClip);
pixman_region_translate (pict->pCompositeClip, pict->pDrawable->x, pict->pDrawable->y);
}
if (pict->pFormat->index.devPrivate)
pixman_image_set_indexed (image, pict->pFormat->index.devPrivate);
return image;
}
static pixman_image_t *
image_from_pict_internal (PicturePtr pict, Bool has_clip, Bool is_alpha_map);
static void
set_image_properties (pixman_image_t *image, PicturePtr pict, Bool is_alpha_map)
{
pixman_repeat_t repeat;
pixman_filter_t filter;
if (pict->transform)
{
pixman_image_set_transform (
image, (pixman_transform_t *)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);
if (pict->alphaMap && !is_alpha_map)
{
pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, TRUE, 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, Bool is_alpha_map)
{
pixman_image_t *image = NULL;
if (!pict)
return NULL;
if (pict->pDrawable)
{
image = create_bits_picture (pict, has_clip);
}
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);
}
}
if (image)
set_image_properties (image, pict, is_alpha_map);
return image;
}
pixman_image_t *
image_from_pict (PicturePtr pict, Bool has_clip)
{
return image_from_pict_internal (pict, has_clip, 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 = miGlyphs;
ps->CompositeRects = miCompositeRects;
ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
ps->AddTraps = fbAddTraps;
ps->AddTriangles = fbAddTriangles;
return TRUE;
}