add the convolution filter from xserver to xorg

This commit is contained in:
Lars Knoll 2005-06-13 14:40:25 +00:00
parent f0ab6d57df
commit 49476ca73c
4 changed files with 208 additions and 125 deletions

View File

@ -2644,20 +2644,14 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
PictVector v; PictVector v;
PictVector unit; PictVector unit;
int i; int i;
int trans_x, trans_y;
BoxRec box; BoxRec box;
miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
if (!pict->transform) {
fbFetch(pict, x, y, width, buffer);
return;
}
fetch = fetchPixelProcForPicture(pict); fetch = fetchPixelProcForPicture(pict);
fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff); fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff);
x += xoff; x += xoff;
y += yoff; y += yoff;
trans_x = x - pict->pDrawable->x;
trans_y = y - pict->pDrawable->y;
v.vector[0] = IntToxFixed(x - pict->pDrawable->x); v.vector[0] = IntToxFixed(x - pict->pDrawable->x);
v.vector[1] = IntToxFixed(y - pict->pDrawable->y); v.vector[1] = IntToxFixed(y - pict->pDrawable->y);
@ -2667,15 +2661,15 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
unit.vector[1] = 0; unit.vector[1] = 0;
unit.vector[2] = xFixed1; unit.vector[2] = xFixed1;
if (!PictureTransformPoint (pict->transform, &v)) { if (pict->transform) {
/* when using convolution filters one might get here without a transform */
if (!PictureTransformPoint (pict->transform, &v))
return; return;
} if (!PictureTransformPoint (pict->transform, &unit))
if (!PictureTransformPoint (pict->transform, &unit)) {
return; return;
} }
if (pict->filter == PictFilterNearest) if (pict->filter == PictFilterNearest) {
{
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents; box = pict->pCompositeClip->extents;
for (i = 0; i < width; ++i) { for (i = 0; i < width; ++i) {
@ -2708,8 +2702,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
buffer[i] = 0; buffer[i] = 0;
} }
} }
} else if (pict->filter == PictFilterBilinear) } else if (pict->filter == PictFilterBilinear) {
{
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents; box = pict->pCompositeClip->extents;
for (i = 0; i < width; ++i) { for (i = 0; i < width; ++i) {
@ -2725,8 +2718,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
x2 = x1 + 1; x2 = x1 + 1;
y1 = xFixedToInt(v.vector[1]); y1 = xFixedToInt(v.vector[1]);
y2 = y1 + 1; y2 = y1 + 1;
if (pict->repeat) if (pict->repeat) {
{
x1 = mod (x1, pict->pDrawable->width); x1 = mod (x1, pict->pDrawable->width);
y1 = mod (y1, pict->pDrawable->height); y1 = mod (y1, pict->pDrawable->height);
x2 = mod (x2, pict->pDrawable->width); x2 = mod (x2, pict->pDrawable->width);
@ -2802,6 +2794,64 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
buffer[i] = tl; buffer[i] = tl;
} }
} }
} else if (pict->filter == PictFilterConvolution) {
xFixed *params = pict->filter_params;
INT32 cwidth = xFixedToInt(params[0]);
INT32 cheight = xFixedToInt(params[1]);
v.vector[0] -= params[0] >> 2;
v.vector[1] -= params[1] >> 2;
params += 2;
for (i = 0; i < width; ++i) {
int x1, x2, y1, y2, x, y;
INT32 srtot, sgtot, sbtot, satot, sum;
xFixed *p = params;
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
x1 = xFixedToInt(v.vector[0]);
x2 = x1 + cwidth;
y1 = xFixedToInt(v.vector[1]);
y2 = y1 + cheight;
srtot = sgtot = sbtot = satot = sum = 0;
for (y = y1; y < y2; y++) {
int ty = (pict->repeat) ? mod (y, pict->pDrawable->height) : y;
for (x = x1; x < x2; x++) {
if (*params) {
int tx = (pict->repeat) ? mod (x, pict->pDrawable->width) : x;
if (POINT_IN_REGION (0, pict->pCompositeClip, tx, ty, &box)) {
FbBits *b = bits + (ty - pict->pDrawable->y)*stride;
CARD32 c = fetch(b, tx - pict->pDrawable->x, indexed);
srtot += Red(c) * *p;
sgtot += Green(c) * *p;
sbtot += Blue(c) * *p;
satot += Alpha(c) * *p;
}
sum += *p;
}
p++;
}
}
if (sum) {
satot /= sum;
srtot /= sum;
sgtot /= sum;
sbtot /= sum;
}
if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff;
if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff;
if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff;
if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff;
buffer[i] = ((satot << 24) |
(srtot << 16) |
(sgtot << 8) |
(sbtot ));
}
} }
} }
@ -2904,6 +2954,8 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
fetchSrc = fbFetchExternalAlpha; fetchSrc = fbFetchExternalAlpha;
else if (data->src->repeat && data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1) else if (data->src->repeat && data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1)
fetchSrc = fbFetchSolid; fetchSrc = fbFetchSolid;
else if (!data->src->transform && data->src->filter != PictFilterConvolution)
fetchSrc = fbFetch;
else else
fetchSrc = fbFetchTransformed; fetchSrc = fbFetchTransformed;
@ -2912,6 +2964,8 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
fetchMask = fbFetchExternalAlpha; fetchMask = fbFetchExternalAlpha;
else if (data->mask->repeat && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1) else if (data->mask->repeat && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
fetchMask = fbFetchSolid; fetchMask = fbFetchSolid;
else if (!data->mask->transform && data->src->filter != PictFilterConvolution)
fetchMask = fbFetch;
else else
fetchMask = fbFetchTransformed; fetchMask = fbFetchTransformed;
} else { } else {

View File

@ -858,8 +858,10 @@ fbComposite (CARD8 op,
maskAlphaMap = pMask->alphaMap != 0; maskAlphaMap = pMask->alphaMap != 0;
} }
if (!pSrc->transform && !(pMask && pMask->transform)) if (!pSrc->transform && !(pMask && pMask->transform)
if (!maskAlphaMap && !srcAlphaMap && !dstAlphaMap) && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
&& (pSrc->filter != PictFilterConvolution)
&& (!pMask || pMask->filter != PictFilterConvolution))
switch (op) { switch (op) {
case PictOpSrc: case PictOpSrc:
#ifdef USE_MMX #ifdef USE_MMX

View File

@ -47,8 +47,6 @@ static int nfilterNames;
* standard but not required filters don't have constant indices * standard but not required filters don't have constant indices
*/ */
int pictFilterConvolution;
int int
PictureGetFilterId (char *filter, int len, Bool makeit) PictureGetFilterId (char *filter, int len, Bool makeit)
{ {
@ -99,6 +97,9 @@ PictureSetDefaultIds (void)
return FALSE; return FALSE;
if (PictureGetFilterId (FilterBest, -1, TRUE) != PictFilterBest) if (PictureGetFilterId (FilterBest, -1, TRUE) != PictFilterBest)
return FALSE; return FALSE;
if (PictureGetFilterId (FilterConvolution, -1, TRUE) != PictFilterConvolution)
return FALSE;
return TRUE; return TRUE;
} }
@ -212,6 +213,26 @@ PictureFindFilter (ScreenPtr pScreen, char *name, int len)
return 0; return 0;
} }
static Bool
convolutionFilterValidateParams (PicturePtr pPicture,
int filter,
xFixed *params,
int nparams)
{
if (nparams < 3)
return FALSE;
if (xFixedFrac (params[0]) || xFixedFrac (params[1]))
return FALSE;
nparams -= 2;
if ((xFixedToInt (params[0]) * xFixedToInt (params[1])) > nparams)
return FALSE;
return TRUE;
}
Bool Bool
PictureSetDefaultFilters (ScreenPtr pScreen) PictureSetDefaultFilters (ScreenPtr pScreen)
{ {
@ -229,6 +250,10 @@ PictureSetDefaultFilters (ScreenPtr pScreen)
return FALSE; return FALSE;
if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterBest)) if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterBest))
return FALSE; return FALSE;
if (PictureAddFilter (pScreen, FilterConvolution, convolutionFilterValidateParams) < 0)
return FALSE;
return TRUE; return TRUE;
} }

View File

@ -117,6 +117,8 @@ typedef struct {
#define PictFilterGood 3 #define PictFilterGood 3
#define PictFilterBest 4 #define PictFilterBest 4
#define PictFilterConvolution 5
typedef struct { typedef struct {
char *alias; char *alias;
int alias_id; int alias_id;