rootless-picture.c [plain text]
#define DEFAULT_LOG_FORMATS 0
#ifdef RENDER
#include "fb.h"
#include "picturestr.h"
#include "mipict.h"
#include "fbpict.h"
#include "rootless.h"
# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
void
RootlessStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value)
{
FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset;
((CARD32 *)line)[offset >> 5] = (value & 0xffffff) | 0xff000000;
}
extern FbCombineFunc fbCombineFuncU[];
extern FbCombineFunc fbCombineFuncC[];
void
RootlessCompositeGeneral(
CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
FbCompositeOperand src[4],msk[4],dst[4],*pmsk;
FbCompositeOperand *srcPict, *srcAlpha;
FbCompositeOperand *dstPict, *dstAlpha;
FbCompositeOperand *mskPict = 0, *mskAlpha = 0;
FbCombineFunc f;
int w;
if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE))
return;
if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE))
return;
if (pDst->format == PICT_x8r8g8b8) {
dst[0].store = RootlessStore_x8r8g8b8;
}
if (pSrc->alphaMap)
{
srcPict = &src[1];
srcAlpha = &src[2];
}
else
{
srcPict = &src[0];
srcAlpha = 0;
}
if (pDst->alphaMap)
{
dstPict = &dst[1];
dstAlpha = &dst[2];
}
else
{
dstPict = &dst[0];
dstAlpha = 0;
}
f = fbCombineFuncU[op];
if (pMask)
{
if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE))
return;
pmsk = msk;
if (pMask->componentAlpha)
f = fbCombineFuncC[op];
if (pMask->alphaMap)
{
mskPict = &msk[1];
mskAlpha = &msk[2];
}
else
{
mskPict = &msk[0];
mskAlpha = 0;
}
}
else
pmsk = 0;
while (height--)
{
w = width;
while (w--)
{
(*f) (src, pmsk, dst);
(*src->over) (src);
(*dst->over) (dst);
if (pmsk)
(*pmsk->over) (pmsk);
}
(*src->down) (src);
(*dst->down) (dst);
if (pmsk)
(*pmsk->down) (pmsk);
}
}
static int rootless_log_pict_formats = DEFAULT_LOG_FORMATS;
static const char *op_name (int op)
{
static const char *ops[] = {
"Clear", "Src", "Dst", "Over", "OverReverse", "In", "InReverse",
"Out", "OutReverse", "Atop", "AtopReverse", "Xor", "Add",
"Saturate", "Maximum",
"DisjointClear", "DisjointSrc", "DisjointDst", "DisjointOver",
"DisjointOverReverse", "DisjointIn", "DisjointInReverse",
"DisjointOut", "DisjointOutReverse", "DisjointAtop",
"DisjointAtopReverse", "DisjointXor", "DisjointMaximum",
"ConjointClear", "ConjointSrc", "ConjointDst", "ConjointOver",
"ConjointOverReverse", "ConjointIn", "ConjointInReverse",
"ConjointOut", "ConjointOutReverse", "ConjointAtop",
"ConjointAtopReverse", "ConjointXor", "ConjointMaximum",
};
if (op >= 0 && op < (int) (sizeof (ops) / sizeof (ops[0])))
return ops[op];
else
return "Unknown";
}
static const char *type_name (int type)
{
switch (type)
{
case PICT_TYPE_OTHER:
return "Other";
case PICT_TYPE_A:
return "A";
case PICT_TYPE_ARGB:
return "ARGB";
case PICT_TYPE_ABGR:
return "ABGR";
case PICT_TYPE_COLOR:
return "Color";
case PICT_TYPE_GRAY:
return "Gray";
default:
return "Unknown";
}
}
static void log_format (int op, unsigned int src,
unsigned int dst, unsigned int mask)
{
struct op {
int op;
unsigned int src, dst, mask;
};
static struct op *ops;
static int n_ops, allocated_ops;
int i;
for (i = 0; i < n_ops; i++)
{
if (ops[i].op == op && ops[i].src == src
&& ops[i].dst == dst && ops[i].mask == mask)
{
return;
}
}
if (n_ops == allocated_ops)
{
allocated_ops *= 2;
ops = realloc (ops, allocated_ops * sizeof (struct op));
}
ops[n_ops].op = op;
ops[n_ops].src = src;
ops[n_ops].dst = dst;
ops[n_ops].mask = mask;
n_ops++;
fprintf (stderr,
"op: %s src (%dbpp %s %04x) dst (%dbpp %s %04x) mask (%dbpp %s %04x)\n",
op_name (op), PICT_FORMAT_BPP (src),
type_name (PICT_FORMAT_TYPE (src)),
src & 0xffff, PICT_FORMAT_BPP (dst),
type_name (PICT_FORMAT_TYPE (dst)),
dst & 0xffff, PICT_FORMAT_BPP (mask),
type_name (PICT_FORMAT_TYPE (mask)),
mask & 0xffff);
}
void
RootlessComposite(
CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
RegionRec region;
int n;
BoxPtr pbox;
CompositeFunc func;
Bool srcRepeat = pSrc->repeat;
Bool maskRepeat = FALSE;
Bool srcAlphaMap = pSrc->alphaMap != 0;
Bool maskAlphaMap = FALSE;
Bool dstAlphaMap = pDst->alphaMap != 0;
int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
int w, h, w_this, h_this;
int dstDepth = pDst->pDrawable->depth;
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
xSrc += pSrc->pDrawable->x;
ySrc += pSrc->pDrawable->y;
if (pMask)
{
xMask += pMask->pDrawable->x;
yMask += pMask->pDrawable->y;
maskRepeat = pMask->repeat;
maskAlphaMap = pMask->alphaMap != 0;
}
if (rootless_log_pict_formats)
{
log_format (op, pSrc->format, pDst->format,
pMask != 0 ? pMask->format : 0);
}
if (!miComputeCompositeRegion (®ion,
pSrc,
pMask,
pDst,
xSrc,
ySrc,
xMask,
yMask,
xDst,
yDst,
width,
height))
return;
if (pDst->pDrawable->type == DRAWABLE_WINDOW
&& pDst->pDrawable->depth == 24
&& pDst->pDrawable->bitsPerPixel == 32)
{
pDst->pDrawable->depth = 32;
}
func = RootlessCompositeGeneral;
if (!maskAlphaMap && !srcAlphaMap && !dstAlphaMap)
switch (op) {
case PictOpOver:
if (pMask)
{
if (srcRepeat &&
pSrc->pDrawable->width == 1 &&
pSrc->pDrawable->height == 1)
{
srcRepeat = FALSE;
if (PICT_FORMAT_COLOR(pSrc->format)) {
switch (pMask->format) {
case PICT_a8:
switch (pDst->format) {
case PICT_r5g6b5:
case PICT_b5g6r5:
func = fbCompositeSolidMask_nx8x0565;
break;
case PICT_r8g8b8:
case PICT_b8g8r8:
func = fbCompositeSolidMask_nx8x0888;
break;
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
func = fbCompositeSolidMask_nx8x8888;
break;
}
break;
case PICT_a8r8g8b8:
if (pMask->componentAlpha) {
switch (pDst->format) {
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
func = fbCompositeSolidMask_nx8888x8888C;
break;
case PICT_r5g6b5:
func = fbCompositeSolidMask_nx8888x0565C;
break;
}
}
break;
case PICT_a8b8g8r8:
if (pMask->componentAlpha) {
switch (pDst->format) {
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
func = fbCompositeSolidMask_nx8888x8888C;
break;
case PICT_b5g6r5:
func = fbCompositeSolidMask_nx8888x0565C;
break;
}
}
break;
case PICT_a1:
switch (pDst->format) {
case PICT_r5g6b5:
case PICT_b5g6r5:
case PICT_r8g8b8:
case PICT_b8g8r8:
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
func = fbCompositeSolidMask_nx1xn;
break;
}
}
}
}
}
else
{
switch (pSrc->format) {
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
switch (pDst->format) {
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
func = fbCompositeSrc_8888x8888;
break;
case PICT_r8g8b8:
func = fbCompositeSrc_8888x0888;
break;
case PICT_r5g6b5:
func = fbCompositeSrc_8888x0565;
break;
}
break;
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
switch (pDst->format) {
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
func = fbCompositeSrc_8888x8888;
break;
case PICT_b8g8r8:
func = fbCompositeSrc_8888x0888;
break;
case PICT_b5g6r5:
func = fbCompositeSrc_8888x0565;
break;
}
break;
case PICT_r5g6b5:
switch (pDst->format) {
case PICT_r5g6b5:
func = fbCompositeSrc_0565x0565;
break;
}
break;
case PICT_b5g6r5:
switch (pDst->format) {
case PICT_b5g6r5:
func = fbCompositeSrc_0565x0565;
break;
}
break;
}
}
break;
case PictOpAdd:
if (pMask == 0)
{
switch (pSrc->format) {
case PICT_a8r8g8b8:
switch (pDst->format) {
case PICT_a8r8g8b8:
func = fbCompositeSrcAdd_8888x8888;
break;
}
break;
case PICT_a8b8g8r8:
switch (pDst->format) {
case PICT_a8b8g8r8:
func = fbCompositeSrcAdd_8888x8888;
break;
}
break;
case PICT_a8:
switch (pDst->format) {
case PICT_a8:
func = fbCompositeSrcAdd_8000x8000;
break;
}
break;
case PICT_a1:
switch (pDst->format) {
case PICT_a1:
func = fbCompositeSrcAdd_1000x1000;
break;
}
break;
}
}
break;
}
n = REGION_NUM_RECTS (®ion);
pbox = REGION_RECTS (®ion);
while (n--)
{
h = pbox->y2 - pbox->y1;
y_src = pbox->y1 - yDst + ySrc;
y_msk = pbox->y1 - yDst + yMask;
y_dst = pbox->y1;
while (h)
{
h_this = h;
w = pbox->x2 - pbox->x1;
x_src = pbox->x1 - xDst + xSrc;
x_msk = pbox->x1 - xDst + xMask;
x_dst = pbox->x1;
if (maskRepeat)
{
y_msk = mod (y_msk, pMask->pDrawable->height);
if (h_this > pMask->pDrawable->height - y_msk)
h_this = pMask->pDrawable->height - y_msk;
}
if (srcRepeat)
{
y_src = mod (y_src, pSrc->pDrawable->height);
if (h_this > pSrc->pDrawable->height - y_src)
h_this = pSrc->pDrawable->height - y_src;
}
while (w)
{
w_this = w;
if (maskRepeat)
{
x_msk = mod (x_msk, pMask->pDrawable->width);
if (w_this > pMask->pDrawable->width - x_msk)
w_this = pMask->pDrawable->width - x_msk;
}
if (srcRepeat)
{
x_src = mod (x_src, pSrc->pDrawable->width);
if (w_this > pSrc->pDrawable->width - x_src)
w_this = pSrc->pDrawable->width - x_src;
}
(*func) (op, pSrc, pMask, pDst,
x_src, y_src, x_msk, y_msk, x_dst, y_dst,
w_this, h_this);
w -= w_this;
x_src += w_this;
x_msk += w_this;
x_dst += w_this;
}
h -= h_this;
y_src += h_this;
y_msk += h_this;
y_dst += h_this;
}
pbox++;
}
REGION_UNINIT (pDst->pDrawable->pScreen, ®ion);
pDst->pDrawable->depth = dstDepth;
}
#endif