Back to index

lightning-sunbird  0.9+nobinonly
fbpict.c
Go to the documentation of this file.
00001 /*
00002  * $Id: fbpict.c,v 1.1.6.3 2005/10/04 03:28:22 vladimir%pobox.com Exp $
00003  *
00004  * Copyright © 2000 SuSE, Inc.
00005  *
00006  * Permission to use, copy, modify, distribute, and sell this software and its
00007  * documentation for any purpose is hereby granted without fee, provided that
00008  * the above copyright notice appear in all copies and that both that
00009  * copyright notice and this permission notice appear in supporting
00010  * documentation, and that the name of SuSE not be used in advertising or
00011  * publicity pertaining to distribution of the software without specific,
00012  * written prior permission.  SuSE makes no representations about the
00013  * suitability of this software for any purpose.  It is provided "as is"
00014  * without express or implied warranty.
00015  *
00016  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
00018  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00019  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
00020  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
00021  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00022  *
00023  * Author:  Keith Packard, SuSE, Inc.
00024  */
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029 #include "pixman-xserver-compat.h"
00030 
00031 #ifdef RENDER
00032 
00033 #include "fbpict.h"
00034 #include "fbmmx.h"
00035 
00036 static CARD32
00037 fbOver (CARD32 x, CARD32 y)
00038 {
00039     CARD16  a = ~x >> 24;
00040     CARD16  t;
00041     CARD32  m,n,o,p;
00042 
00043     m = FbOverU(x,y,0,a,t);
00044     n = FbOverU(x,y,8,a,t);
00045     o = FbOverU(x,y,16,a,t);
00046     p = FbOverU(x,y,24,a,t);
00047     return m|n|o|p;
00048 }
00049 
00050 static CARD32
00051 fbOver24 (CARD32 x, CARD32 y)
00052 {
00053     CARD16  a = ~x >> 24;
00054     CARD16  t;
00055     CARD32  m,n,o;
00056 
00057     m = FbOverU(x,y,0,a,t);
00058     n = FbOverU(x,y,8,a,t);
00059     o = FbOverU(x,y,16,a,t);
00060     return m|n|o;
00061 }
00062 
00063 static CARD32
00064 fbIn (CARD32 x, CARD8 y)
00065 {
00066     CARD16  a = y;
00067     CARD16  t;
00068     CARD32  m,n,o,p;
00069 
00070     m = FbInU(x,0,a,t);
00071     n = FbInU(x,8,a,t);
00072     o = FbInU(x,16,a,t);
00073     p = FbInU(x,24,a,t);
00074     return m|n|o|p;
00075 }
00076 
00077 static CARD32
00078 fbIn24 (CARD32 x, CARD8 y)
00079 {
00080     CARD16  a = y;
00081     CARD16  t;
00082     CARD32  m,n,o,p;
00083 
00084     m = FbInU(x,0,a,t);
00085     n = FbInU(x,8,a,t);
00086     o = FbInU(x,16,a,t);
00087     p = (y << 24);
00088     return m|n|o|p;
00089 }
00090 
00091 #define genericCombine24(a,b,c,d) (((a)*(c)+(b)*(d)))
00092 
00093 /*
00094  * This macro does src IN mask OVER dst when src and dst are 0888.
00095  * If src has alpha, this will not work
00096  */
00097 #define inOver0888(alpha, source, destval, dest) { \
00098        CARD32 dstrb=destval&0xFF00FF; CARD32 dstag=(destval>>8)&0xFF00FF; \
00099        CARD32 drb=((source&0xFF00FF)-dstrb)*alpha; CARD32 dag=(((source>>8)&0xFF00FF)-dstag)*alpha; \
00100        dest =((((drb>>8) + dstrb) & 0x00FF00FF) | ((((dag>>8) + dstag) << 8) & 0xFF00FF00)); \
00101        }
00102 
00103 /*
00104  * This macro does src IN mask OVER dst when src and dst are 0565 and
00105  * mask is a 5-bit alpha value.  Again, if src has alpha, this will not
00106  * work.
00107  */
00108 
00109 #define inOver0565(alpha, source, destval, dest) { \
00110        CARD16 dstrb = destval & 0xf81f; CARD16 dstg  = destval & 0x7e0; \
00111        CARD32 drb = ((source&0xf81f)-dstrb)*alpha; CARD32 dg=((source & 0x7e0)-dstg)*alpha; \
00112        dest = ((((drb>>5) + dstrb)&0xf81f) | (((dg>>5)  + dstg) & 0x7e0)); \
00113        }
00114 
00115 #define inOver2x0565(alpha, source, destval, dest) { \
00116        CARD32 dstrb = destval & 0x07e0f81f; CARD32 dstg  = (destval & 0xf81f07e0)>>5; \
00117        CARD32 drb = ((source&0x07e0f81f)-dstrb)*alpha; CARD32 dg=(((source & 0xf81f07e0)>>5)-dstg)*alpha; \
00118        dest = ((((drb>>5) + dstrb)&0x07e0f81f) | ((((dg>>5)  + dstg)<<5) & 0xf81f07e0)); \
00119        }
00120 
00121 #if IMAGE_BYTE_ORDER == LSBFirst
00122 #      define setupPackedReader(count,temp,where,workingWhere,workingVal) count=(long)where; \
00123                                    temp=count&3; \
00124                                    where-=temp; \
00125                                    workingWhere=(CARD32 *)where; \
00126                                    workingVal=*workingWhere++; \
00127                                    count=4-temp; \
00128                                    workingVal>>=(8*temp)
00129 #      define readPacked(where,x,y,z) {if(!(x)) { (x)=4; y=*z++; } where=(y)&0xff; (y)>>=8; (x)--;}
00130 #      define readPackedSource(where) readPacked(where,ws,workingSource,wsrc)
00131 #      define readPackedDest(where) readPacked(where,wd,workingiDest,widst)
00132 #      define writePacked(what) workingoDest>>=8; workingoDest|=(what<<24); ww--; if(!ww) { ww=4; *wodst++=workingoDest; }
00133 #else
00134 #      define setupPackedReader(count,temp,where,workingWhere,workingVal) count=(long)where; \
00135                                    temp=count&3; \
00136                                    where-=temp; \
00137                                    workingWhere=(CARD32 *)where; \
00138                                    workingVal=*workingWhere++; \
00139                                    count=4-temp; \
00140                                    workingVal<<=(8*temp)
00141 #      define readPacked(where,x,y,z) {if(!(x)) { (x)=4; y=*z++; } where=(y)>>24; (y)<<=8; (x)--;}
00142 #      define readPackedSource(where) readPacked(where,ws,workingSource,wsrc)
00143 #      define readPackedDest(where) readPacked(where,wd,workingiDest,widst)
00144 #      define writePacked(what) workingoDest<<=8; workingoDest|=what; ww--; if(!ww) { ww=4; *wodst++=workingoDest; }
00145 #endif
00146 /*
00147  * Naming convention:
00148  *
00149  *  opSRCxMASKxDST
00150  */
00151 
00152 static void
00153 fbCompositeSolidMask_nx8x8888 (pixman_operator_t   op,
00154                             PicturePtr pSrc,
00155                             PicturePtr pMask,
00156                             PicturePtr pDst,
00157                             INT16      xSrc,
00158                             INT16      ySrc,
00159                             INT16      xMask,
00160                             INT16      yMask,
00161                             INT16      xDst,
00162                             INT16      yDst,
00163                             CARD16     width,
00164                             CARD16     height)
00165 {
00166     CARD32    src, srca;
00167     CARD32    *dstLine, *dst, d, dstMask;
00168     CARD8     *maskLine, *mask, m;
00169     FbStride  dstStride, maskStride;
00170     CARD16    w;
00171 
00172     fbComposeGetSolid(pSrc, pDst, src);
00173 
00174     dstMask = FbFullMask (pDst->pDrawable->depth);
00175     srca = src >> 24;
00176     if (src == 0)
00177        return;
00178 
00179     fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
00180     fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
00181 
00182     while (height--)
00183     {
00184        dst = dstLine;
00185        dstLine += dstStride;
00186        mask = maskLine;
00187        maskLine += maskStride;
00188        w = width;
00189 
00190        while (w--)
00191        {
00192            m = *mask++;
00193            if (m == 0xff)
00194            {
00195               if (srca == 0xff)
00196                   *dst = src & dstMask;
00197               else
00198                   *dst = fbOver (src, *dst) & dstMask;
00199            }
00200            else if (m)
00201            {
00202               d = fbIn (src, m);
00203               *dst = fbOver (d, *dst) & dstMask;
00204            }
00205            dst++;
00206        }
00207     }
00208 }
00209 
00210 static void
00211 fbCompositeSolidMask_nx8888x8888C (pixman_operator_t   op,
00212                                PicturePtr pSrc,
00213                                PicturePtr pMask,
00214                                PicturePtr pDst,
00215                                INT16      xSrc,
00216                                INT16      ySrc,
00217                                INT16      xMask,
00218                                INT16      yMask,
00219                                INT16      xDst,
00220                                INT16      yDst,
00221                                CARD16     width,
00222                                CARD16     height)
00223 {
00224     CARD32    src, srca;
00225     CARD32    *dstLine, *dst, d, dstMask;
00226     CARD32    *maskLine, *mask, ma;
00227     FbStride  dstStride, maskStride;
00228     CARD16    w;
00229     CARD32    m, n, o, p;
00230 
00231     fbComposeGetSolid(pSrc, pDst, src);
00232 
00233     dstMask = FbFullMask (pDst->pDrawable->depth);
00234     srca = src >> 24;
00235     if (src == 0)
00236        return;
00237 
00238     fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
00239     fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1);
00240 
00241     while (height--)
00242     {
00243        dst = dstLine;
00244        dstLine += dstStride;
00245        mask = maskLine;
00246        maskLine += maskStride;
00247        w = width;
00248 
00249        while (w--)
00250        {
00251            ma = *mask++;
00252            if (ma == 0xffffffff)
00253            {
00254               if (srca == 0xff)
00255                   *dst = src & dstMask;
00256               else
00257                   *dst = fbOver (src, *dst) & dstMask;
00258            }
00259            else if (ma)
00260            {
00261               d = *dst;
00262 #define FbInOverC(src,srca,msk,dst,i,result) { \
00263     CARD16  __a = FbGet8(msk,i); \
00264     CARD32  __t, __ta; \
00265     CARD32  __i; \
00266     __t = FbIntMult (FbGet8(src,i), __a,__i); \
00267     __ta = (CARD8) ~FbIntMult (srca, __a,__i); \
00268     __t = __t + FbIntMult(FbGet8(dst,i),__ta,__i); \
00269     __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \
00270     result = __t << (i); \
00271 }
00272               FbInOverC (src, srca, ma, d, 0, m);
00273               FbInOverC (src, srca, ma, d, 8, n);
00274               FbInOverC (src, srca, ma, d, 16, o);
00275               FbInOverC (src, srca, ma, d, 24, p);
00276               *dst = m|n|o|p;
00277            }
00278            dst++;
00279        }
00280     }
00281 }
00282 
00283 #define srcAlphaCombine24(a,b) genericCombine24(a,b,srca,srcia)
00284 static void
00285 fbCompositeSolidMask_nx8x0888 (pixman_operator_t   op,
00286                             PicturePtr pSrc,
00287                             PicturePtr pMask,
00288                             PicturePtr pDst,
00289                             INT16      xSrc,
00290                             INT16      ySrc,
00291                             INT16      xMask,
00292                             INT16      yMask,
00293                             INT16      xDst,
00294                             INT16      yDst,
00295                             CARD16     width,
00296                             CARD16     height)
00297 {
00298     CARD32    src, srca, srcia;
00299     CARD8     *dstLine, *dst, *edst;
00300     CARD8     *maskLine, *mask, m;
00301     FbStride  dstStride, maskStride;
00302     CARD16    w;
00303        CARD32 rs,gs,bs,rd,gd,bd;
00304 
00305     fbComposeGetSolid(pSrc, pDst, src);
00306 
00307     srca = src >> 24;
00308     srcia = 255-srca;
00309     if (src == 0)
00310        return;
00311 
00312        rs=src&0xff;
00313        gs=(src>>8)&0xff;
00314        bs=(src>>16)&0xff;
00315 
00316     fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 3);
00317     fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
00318 
00319     while (height--)
00320        {
00321               /* fixme: cleanup unused */
00322               unsigned long wt,wd;
00323               CARD32 workingiDest;
00324               CARD32 *widst;
00325 
00326               edst=dst = dstLine;
00327               dstLine += dstStride;
00328               mask = maskLine;
00329               maskLine += maskStride;
00330               w = width;
00331 
00332 #ifndef NO_MASKED_PACKED_READ
00333               setupPackedReader(wd,wt,edst,widst,workingiDest);
00334 #endif
00335 
00336               while (w--)
00337               {
00338 #ifndef NO_MASKED_PACKED_READ
00339                      readPackedDest(rd);
00340                      readPackedDest(gd);
00341                      readPackedDest(bd);
00342 #else
00343                      rd= *edst++;
00344                      gd= *edst++;
00345                      bd= *edst++;
00346 #endif
00347                      m = *mask++;
00348                      if (m == 0xff)
00349                      {
00350                             if (srca == 0xff)
00351                             {
00352                                    *dst++=rs;
00353                                    *dst++=gs;
00354                                    *dst++=bs;
00355                             }
00356                             else
00357                             {
00358                                    *dst++=(srcAlphaCombine24(rs, rd)>>8);
00359                                    *dst++=(srcAlphaCombine24(gs, gd)>>8);
00360                                    *dst++=(srcAlphaCombine24(bs, bd)>>8);
00361                             }
00362                      }
00363                      else if (m)
00364                      {
00365                             int na=(srca*(int)m)>>8;
00366                             int nia=255-na;
00367                             *dst++=(genericCombine24(rs, rd, na, nia)>>8);
00368                             *dst++=(genericCombine24(gs, gd, na, nia)>>8);
00369                             *dst++=(genericCombine24(bs, bd, na, nia)>>8);
00370                      }
00371                      else
00372                      {
00373                             dst+=3;
00374                      }
00375               }
00376        }
00377 }
00378 
00379 static void
00380 fbCompositeSolidMask_nx8x0565 (pixman_operator_t      op,
00381                               PicturePtr pSrc,
00382                               PicturePtr pMask,
00383                               PicturePtr pDst,
00384                               INT16      xSrc,
00385                               INT16      ySrc,
00386                               INT16      xMask,
00387                               INT16      yMask,
00388                               INT16      xDst,
00389                               INT16      yDst,
00390                               CARD16     width,
00391                               CARD16     height)
00392 {
00393     CARD32    src, srca8, srca5;
00394     CARD16    *dstLine, *dst;
00395     CARD16    d;
00396     CARD32    t;
00397     CARD8     *maskLine, *mask, m;
00398     FbStride  dstStride, maskStride;
00399     CARD16    w,src16;
00400 
00401     fbComposeGetSolid(pSrc, pDst, src);
00402 
00403     if (src == 0)
00404        return;
00405 
00406     srca8 = (src >> 24);
00407     srca5 = (srca8 >> 3);
00408 
00409     src16 = cvt8888to0565(src);
00410 
00411     fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
00412     fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
00413 
00414     while (height--)
00415     {
00416        dst = dstLine;
00417        dstLine += dstStride;
00418        mask = maskLine;
00419        maskLine += maskStride;
00420        w = width;
00421 
00422        while (w--)
00423        {
00424            m = *mask++;
00425            if (m == 0)
00426               dst++;
00427            else if (srca5 == (0xff >> 3))
00428            {
00429               if (m == 0xff)
00430                   *dst++ = src16;
00431               else
00432               {
00433                   d = *dst;
00434                   m >>= 3;
00435                   inOver0565 (m, src16, d, *dst++);
00436               }
00437            }
00438            else
00439            {
00440               d = *dst;
00441               if (m == 0xff)
00442               {
00443                   t = fbOver24 (src, cvt0565to0888 (d));
00444               }
00445               else
00446               {
00447                   t = fbIn (src, m);
00448                   t = fbOver (t, cvt0565to0888 (d));
00449               }
00450               *dst++ = cvt8888to0565 (t);
00451            }
00452        }
00453     }
00454 }
00455 
00456 static void
00457 fbCompositeSolidMask_nx8888x0565 (pixman_operator_t      op,
00458                               PicturePtr pSrc,
00459                               PicturePtr pMask,
00460                               PicturePtr pDst,
00461                               INT16      xSrc,
00462                               INT16      ySrc,
00463                               INT16      xMask,
00464                               INT16      yMask,
00465                               INT16      xDst,
00466                               INT16      yDst,
00467                               CARD16     width,
00468                               CARD16     height)
00469 {
00470     CARD32    src, srca8, srca5;
00471     CARD16    *dstLine, *dst;
00472     CARD16    d;
00473     CARD32    *maskLine, *mask;
00474     CARD32    t;
00475     CARD8     m;
00476     FbStride  dstStride, maskStride;
00477     CARD16    w, src16;
00478 
00479     fbComposeGetSolid(pSrc, pDst, src);
00480 
00481     if (src == 0)
00482        return;
00483 
00484     srca8 = src >> 24;
00485     srca5 = srca8 >> 3;
00486     src16 = cvt8888to0565(src);
00487 
00488     fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
00489     fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1);
00490 
00491     while (height--)
00492     {
00493        dst = dstLine;
00494        dstLine += dstStride;
00495        mask = maskLine;
00496        maskLine += maskStride;
00497        w = width;
00498 
00499        while (w--)
00500        {
00501            m = *mask++ >> 24;
00502            if (m == 0)
00503               dst++;
00504            else if (srca5 == (0xff >> 3))
00505            {
00506               if (m == 0xff)
00507                   *dst++ = src16;
00508               else
00509               {
00510                   d = *dst;
00511                   m >>= 3;
00512                   inOver0565 (m, src16, d, *dst++);
00513               }
00514            }
00515            else
00516            {
00517               if (m == 0xff)
00518               {
00519                   d = *dst;
00520                   t = fbOver24 (src, cvt0565to0888 (d));
00521                   *dst++ = cvt8888to0565 (t);
00522               }
00523               else
00524               {
00525                   d = *dst;
00526                   t = fbIn (src, m);
00527                   t = fbOver (t, cvt0565to0888 (d));
00528                   *dst++ = cvt8888to0565 (t);
00529               }
00530            }
00531        }
00532     }
00533 }
00534 
00535 static void
00536 fbCompositeSolidMask_nx8888x0565C (pixman_operator_t      op,
00537                                PicturePtr pSrc,
00538                                PicturePtr pMask,
00539                                PicturePtr pDst,
00540                                INT16      xSrc,
00541                                INT16      ySrc,
00542                                INT16      xMask,
00543                                INT16      yMask,
00544                                INT16      xDst,
00545                                INT16      yDst,
00546                                CARD16     width,
00547                                CARD16     height)
00548 {
00549     CARD32    src, srca;
00550     CARD16    src16;
00551     CARD16    *dstLine, *dst;
00552     CARD32    d;
00553     CARD32    *maskLine, *mask, ma;
00554     FbStride  dstStride, maskStride;
00555     CARD16    w;
00556     CARD32    m, n, o;
00557 
00558     fbComposeGetSolid(pSrc, pDst, src);
00559 
00560     srca = src >> 24;
00561     if (src == 0)
00562        return;
00563 
00564     src16 = cvt8888to0565(src);
00565 
00566     fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
00567     fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1);
00568 
00569     while (height--)
00570     {
00571        dst = dstLine;
00572        dstLine += dstStride;
00573        mask = maskLine;
00574        maskLine += maskStride;
00575        w = width;
00576 
00577        while (w--)
00578        {
00579            ma = *mask++;
00580            if (ma == 0xffffffff)
00581            {
00582               if (srca == 0xff)
00583               {
00584                   *dst = src16;
00585               }
00586               else
00587               {
00588                   d = *dst;
00589                   d = fbOver24 (src, cvt0565to0888(d));
00590                   *dst = cvt8888to0565(d);
00591               }
00592            }
00593            else if (ma)
00594            {
00595               d = *dst;
00596               d = cvt0565to0888(d);
00597               FbInOverC (src, srca, ma, d, 0, m);
00598               FbInOverC (src, srca, ma, d, 8, n);
00599               FbInOverC (src, srca, ma, d, 16, o);
00600               d = m|n|o;
00601               *dst = cvt8888to0565(d);
00602            }
00603            dst++;
00604        }
00605     }
00606 }
00607 
00608 static void
00609 fbCompositeSrc_8888x8888 (pixman_operator_t  op,
00610                       PicturePtr pSrc,
00611                       PicturePtr pMask,
00612                       PicturePtr pDst,
00613                       INT16      xSrc,
00614                       INT16      ySrc,
00615                       INT16      xMask,
00616                       INT16      yMask,
00617                       INT16      xDst,
00618                       INT16      yDst,
00619                       CARD16     width,
00620                       CARD16     height)
00621 {
00622     CARD32    *dstLine, *dst, dstMask;
00623     CARD32    *srcLine, *src, s;
00624     FbStride  dstStride, srcStride;
00625     CARD8     a;
00626     CARD16    w;
00627 
00628     fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
00629     fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
00630 
00631     dstMask = FbFullMask (pDst->pDrawable->depth);
00632 
00633     while (height--)
00634     {
00635        dst = dstLine;
00636        dstLine += dstStride;
00637        src = srcLine;
00638        srcLine += srcStride;
00639        w = width;
00640 
00641        while (w--)
00642        {
00643            s = *src++;
00644            a = s >> 24;
00645            if (a == 0xff)
00646               *dst = s & dstMask;
00647            else if (a)
00648               *dst = fbOver (s, *dst) & dstMask;
00649            dst++;
00650        }
00651     }
00652 }
00653 
00654 static void
00655 fbCompositeSrc_8888x0888 (pixman_operator_t  op,
00656                       PicturePtr pSrc,
00657                       PicturePtr pMask,
00658                       PicturePtr pDst,
00659                       INT16      xSrc,
00660                       INT16      ySrc,
00661                       INT16      xMask,
00662                       INT16      yMask,
00663                       INT16      xDst,
00664                       INT16      yDst,
00665                       CARD16     width,
00666                       CARD16     height)
00667 {
00668     CARD8     *dstLine, *dst;
00669     CARD32    d;
00670     CARD32    *srcLine, *src, s;
00671     CARD8     a;
00672     FbStride  dstStride, srcStride;
00673     CARD16    w;
00674 
00675     fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 3);
00676     fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
00677 
00678     while (height--)
00679     {
00680        dst = dstLine;
00681        dstLine += dstStride;
00682        src = srcLine;
00683        srcLine += srcStride;
00684        w = width;
00685 
00686        while (w--)
00687        {
00688            s = *src++;
00689            a = s >> 24;
00690            if (a)
00691            {
00692               if (a == 0xff)
00693                   d = s;
00694               else
00695                   d = fbOver24 (s, Fetch24(dst));
00696               Store24(dst,d);
00697            }
00698            dst += 3;
00699        }
00700     }
00701 }
00702 
00703 static void
00704 fbCompositeSrc_8888x0565 (pixman_operator_t  op,
00705                       PicturePtr pSrc,
00706                       PicturePtr pMask,
00707                       PicturePtr pDst,
00708                       INT16      xSrc,
00709                       INT16      ySrc,
00710                       INT16      xMask,
00711                       INT16      yMask,
00712                       INT16      xDst,
00713                       INT16      yDst,
00714                       CARD16     width,
00715                       CARD16     height)
00716 {
00717     CARD16    *dstLine, *dst;
00718     CARD32    d;
00719     CARD32    *srcLine, *src, s;
00720     CARD8     a;
00721     FbStride  dstStride, srcStride;
00722     CARD16    w;
00723 
00724     fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
00725     fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
00726 
00727     while (height--)
00728     {
00729        dst = dstLine;
00730        dstLine += dstStride;
00731        src = srcLine;
00732        srcLine += srcStride;
00733        w = width;
00734 
00735        while (w--)
00736        {
00737            s = *src++;
00738            a = s >> 24;
00739            if (a)
00740            {
00741               if (a == 0xff)
00742                   d = s;
00743               else
00744               {
00745                   d = *dst;
00746                   d = fbOver24 (s, cvt0565to0888(d));
00747               }
00748               *dst = cvt8888to0565(d);
00749            }
00750            dst++;
00751        }
00752     }
00753 }
00754 
00755 
00756 
00757 static void
00758 fbCompositeSrcAdd_8000x8000 (pixman_operator_t     op,
00759                           PicturePtr pSrc,
00760                           PicturePtr pMask,
00761                           PicturePtr pDst,
00762                           INT16      xSrc,
00763                           INT16      ySrc,
00764                           INT16      xMask,
00765                           INT16      yMask,
00766                           INT16      xDst,
00767                           INT16      yDst,
00768                           CARD16     width,
00769                           CARD16     height)
00770 {
00771     CARD8     *dstLine, *dst;
00772     CARD8     *srcLine, *src;
00773     FbStride  dstStride, srcStride;
00774     CARD16    w;
00775     CARD8     s, d;
00776     CARD16    t;
00777 
00778     fbComposeGetStart (pSrc, xSrc, ySrc, CARD8, srcStride, srcLine, 1);
00779     fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1);
00780 
00781     while (height--)
00782     {
00783        dst = dstLine;
00784        dstLine += dstStride;
00785        src = srcLine;
00786        srcLine += srcStride;
00787        w = width;
00788 
00789        while (w--)
00790        {
00791            s = *src++;
00792            if (s)
00793            {
00794               if (s != 0xff)
00795               {
00796                   d = *dst;
00797                   t = d + s;
00798                   s = t | (0 - (t >> 8));
00799               }
00800               *dst = s;
00801            }
00802            dst++;
00803        }
00804     }
00805 }
00806 
00807 static void
00808 fbCompositeSrcAdd_8888x8888 (pixman_operator_t   op,
00809                           PicturePtr pSrc,
00810                           PicturePtr pMask,
00811                           PicturePtr pDst,
00812                           INT16      xSrc,
00813                           INT16      ySrc,
00814                           INT16      xMask,
00815                           INT16      yMask,
00816                           INT16      xDst,
00817                           INT16      yDst,
00818                           CARD16     width,
00819                           CARD16     height)
00820 {
00821     CARD32    *dstLine, *dst;
00822     CARD32    *srcLine, *src;
00823     FbStride  dstStride, srcStride;
00824     CARD16    w;
00825     CARD32    s, d;
00826     CARD16    t;
00827     CARD32    m,n,o,p;
00828 
00829     fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
00830     fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
00831 
00832     while (height--)
00833     {
00834        dst = dstLine;
00835        dstLine += dstStride;
00836        src = srcLine;
00837        srcLine += srcStride;
00838        w = width;
00839 
00840        while (w--)
00841        {
00842            s = *src++;
00843            if (s)
00844            {
00845               if (s != 0xffffffff)
00846               {
00847                   d = *dst;
00848                   if (d)
00849                   {
00850                      m = FbAdd(s,d,0,t);
00851                      n = FbAdd(s,d,8,t);
00852                      o = FbAdd(s,d,16,t);
00853                      p = FbAdd(s,d,24,t);
00854                      s = m|n|o|p;
00855                   }
00856               }
00857               *dst = s;
00858            }
00859            dst++;
00860        }
00861     }
00862 }
00863 
00864 static void
00865 fbCompositeSrcAdd_1000x1000 (pixman_operator_t   op,
00866                           PicturePtr pSrc,
00867                           PicturePtr pMask,
00868                           PicturePtr pDst,
00869                           INT16      xSrc,
00870                           INT16      ySrc,
00871                           INT16      xMask,
00872                           INT16      yMask,
00873                           INT16      xDst,
00874                           INT16      yDst,
00875                           CARD16     width,
00876                           CARD16     height)
00877 {
00878     FbBits    *dstBits, *srcBits;
00879     FbStride  dstStride, srcStride;
00880     int              dstBpp, srcBpp;
00881     int              dstXoff, dstYoff;
00882     int              srcXoff, srcYoff;
00883 
00884     fbGetDrawable(pSrc->pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
00885 
00886     fbGetDrawable(pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
00887 
00888     fbBlt (srcBits + srcStride * (ySrc + srcYoff),
00889           srcStride,
00890           xSrc + srcXoff,
00891 
00892           dstBits + dstStride * (yDst + dstYoff),
00893           dstStride,
00894           xDst + dstXoff,
00895 
00896           width,
00897           height,
00898 
00899           GXor,
00900           FB_ALLONES,
00901           srcBpp,
00902 
00903           FALSE,
00904           FALSE);
00905 }
00906 
00907 static void
00908 fbCompositeSolidMask_nx1xn (pixman_operator_t   op,
00909                          PicturePtr pSrc,
00910                          PicturePtr pMask,
00911                          PicturePtr pDst,
00912                          INT16      xSrc,
00913                          INT16      ySrc,
00914                          INT16      xMask,
00915                          INT16      yMask,
00916                          INT16      xDst,
00917                          INT16      yDst,
00918                          CARD16     width,
00919                          CARD16     height)
00920 {
00921     FbBits    *dstBits;
00922     FbStip    *maskBits;
00923     FbStride  dstStride, maskStride;
00924     int              dstBpp, maskBpp;
00925     int              dstXoff, dstYoff;
00926     int              maskXoff, maskYoff;
00927     FbBits    src;
00928 
00929     fbComposeGetSolid(pSrc, pDst, src);
00930 
00931     if ((src & 0xff000000) != 0xff000000)
00932     {
00933        pixman_compositeGeneral  (op, pSrc, pMask, pDst,
00934                           xSrc, ySrc, xMask, yMask, xDst, yDst,
00935                           width, height);
00936        return;
00937     }
00938     FbGetStipPixels (pMask->pixels, maskBits, maskStride, maskBpp, maskXoff, maskYoff);
00939     fbGetDrawable (pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
00940 
00941     switch (dstBpp) {
00942     case 32:
00943        break;
00944     case 24:
00945        break;
00946     case 16:
00947        src = cvt8888to0565(src);
00948        break;
00949     }
00950 
00951     src = fbReplicatePixel (src, dstBpp);
00952 
00953     fbBltOne (maskBits + maskStride * (yMask + maskYoff),
00954              maskStride,
00955              xMask + maskXoff,
00956 
00957              dstBits + dstStride * (yDst + dstYoff),
00958              dstStride,
00959              (xDst + dstXoff) * dstBpp,
00960              dstBpp,
00961 
00962              width * dstBpp,
00963              height,
00964 
00965              0x0,
00966              src,
00967              FB_ALLONES,
00968              0x0);
00969 }
00970 
00971 /* prototype to help with merging */
00972 static void
00973 fbCompositeSrcSrc_nxn  (pixman_operator_t op,
00974                      PicturePtr pSrc,
00975                      PicturePtr pMask,
00976                      PicturePtr pDst,
00977                      INT16      xSrc,
00978                      INT16      ySrc,
00979                      INT16      xMask,
00980                      INT16      yMask,
00981                      INT16      xDst,
00982                      INT16      yDst,
00983                      CARD16     width,
00984                      CARD16     height);
00985 /*
00986  * Apply a constant alpha value in an over computation
00987  */
00988 static void
00989 fbCompositeTrans_0565xnx0565(pixman_operator_t      op,
00990                           PicturePtr pSrc,
00991                           PicturePtr pMask,
00992                           PicturePtr pDst,
00993                           INT16      xSrc,
00994                           INT16      ySrc,
00995                           INT16      xMask,
00996                           INT16      yMask,
00997                           INT16      xDst,
00998                           INT16      yDst,
00999                           CARD16     width,
01000                           CARD16     height)
01001 {
01002     CARD16    *dstLine, *dst;
01003     CARD16    *srcLine, *src;
01004     FbStride  dstStride, srcStride;
01005     CARD16    w;
01006     FbBits    mask;
01007     CARD8     maskAlpha;
01008     CARD16    s_16, d_16;
01009     CARD32    s_32, d_32;
01010 
01011     fbComposeGetSolid (pMask, pDst, mask);
01012     maskAlpha = mask >> 27;
01013 
01014     if (!maskAlpha)
01015        return;
01016     if (maskAlpha == 0xff)
01017     {
01018        fbCompositeSrcSrc_nxn (PIXMAN_OPERATOR_SRC, pSrc, pMask, pDst,
01019                             xSrc, ySrc, xMask, yMask, xDst, yDst,
01020                             width, height);
01021        return;
01022     }
01023 
01024     fbComposeGetStart (pSrc, xSrc, ySrc, CARD16, srcStride, srcLine, 1);
01025     fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
01026 
01027     while (height--)
01028        {
01029               CARD32 *isrc, *idst;
01030               dst = dstLine;
01031               dstLine += dstStride;
01032               src = srcLine;
01033               srcLine += srcStride;
01034               w = width;
01035 
01036               if(((long)src&1)==1)
01037               {
01038                      s_16 = *src++;
01039                      d_16 = *dst;
01040                      inOver0565(maskAlpha, s_16, d_16, *dst++);
01041                      w--;
01042               }
01043               isrc=(CARD32 *)src;
01044               if(((long)dst&1)==0)
01045               {
01046                      idst=(CARD32 *)dst;
01047                      while (w>1)
01048                      {
01049                             s_32 = *isrc++;
01050                             d_32 = *idst;
01051                             inOver2x0565(maskAlpha,s_32,d_32,*idst++);
01052                             w-=2;
01053                      }
01054                      dst=(CARD16 *)idst;
01055               }
01056               else
01057               {
01058                   while (w > 1)
01059                   {
01060                      s_32 = *isrc++;
01061 #if IMAGE_BYTE_ORDER == LSBFirst
01062                             s_16=s_32&0xffff;
01063 #else
01064                             s_16=s_32>>16;
01065 #endif
01066                             d_16 = *dst;
01067                             inOver0565(maskAlpha, s_16, d_16, *dst++);
01068 #if IMAGE_BYTE_ORDER == LSBFirst
01069                             s_16=s_32>>16;
01070 #else
01071                             s_16=s_32&0xffff;
01072 #endif
01073                      d_16 = *dst;
01074                      inOver0565(maskAlpha, s_16, d_16, *dst++);
01075                      w-=2;
01076                   }
01077               }
01078               src=(CARD16 *)isrc;
01079               if(w!=0)
01080               {
01081                      s_16 = *src;
01082                      d_16 = *dst;
01083                      inOver0565(maskAlpha, s_16, d_16, *dst);
01084               }
01085        }
01086 }
01087 
01088 
01089 
01090 /* macros for "i can't believe it's not fast" packed pixel handling */
01091 #define alphamaskCombine24(a,b) genericCombine24(a,b,maskAlpha,maskiAlpha)
01092 static void
01093 fbCompositeTrans_0888xnx0888(pixman_operator_t      op,
01094                           PicturePtr pSrc,
01095                           PicturePtr pMask,
01096                           PicturePtr pDst,
01097                           INT16      xSrc,
01098                           INT16      ySrc,
01099                           INT16      xMask,
01100                           INT16      yMask,
01101                           INT16      xDst,
01102                           INT16      yDst,
01103                           CARD16     width,
01104                           CARD16     height)
01105 {
01106     CARD8     *dstLine, *dst,*idst;
01107     CARD8     *srcLine, *src;
01108     FbStride  dstStride, srcStride;
01109     CARD16    w;
01110     FbBits    mask;
01111     CARD16    maskAlpha,maskiAlpha;
01112 
01113     fbComposeGetSolid (pMask, pDst, mask);
01114     maskAlpha = mask >> 24;
01115        maskiAlpha= 255-maskAlpha;
01116 
01117     if (!maskAlpha)
01118        return;
01119     /*
01120     if (maskAlpha == 0xff)
01121     {
01122        fbCompositeSrc_0888x0888 (op, pSrc, pMask, pDst,
01123                               xSrc, ySrc, xMask, yMask, xDst, yDst,
01124                               width, height);
01125        return;
01126     }
01127     */
01128 
01129     fbComposeGetStart (pSrc, xSrc, ySrc, CARD8, srcStride, srcLine, 3);
01130     fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 3);
01131 
01132        {
01133               unsigned long ws,wt;
01134               CARD32 workingSource;
01135               CARD32 *wsrc, *wdst, *widst;
01136               CARD32 rs, rd, nd;
01137               CARD8 *isrc;
01138 
01139               /* are xSrc and xDst at the same alignment?  if not, we need to be complicated :)*/
01140               /* if(0==0) */
01141               if( (((xSrc*3)&3)!=((xDst*3)&3)) || ((srcStride&3)!=(dstStride&3)))
01142               {
01143                      while (height--)
01144                      {
01145                             dst = dstLine;
01146                             dstLine += dstStride;
01147                             isrc = src = srcLine;
01148                             srcLine += srcStride;
01149                             w = width*3;
01150 
01151                             setupPackedReader(ws,wt,isrc,wsrc,workingSource);
01152 
01153                             /* get to word aligned */
01154                             switch(!(long)dst&3)
01155                             {
01156                                    case 1:
01157                                           readPackedSource(rs);
01158                                           /* *dst++=alphamaskCombine24(rs, *dst)>>8; */
01159                                           rd=*dst;  /* make gcc happy.  hope it doens't cost us too much performance*/
01160                                           *dst++=alphamaskCombine24(rs, rd)>>8;
01161                                           w--; if(w==0) break;
01162                                    case 2:
01163                                           readPackedSource(rs);
01164                                           rd=*dst;
01165                                           *dst++=alphamaskCombine24(rs, rd)>>8;
01166                                           w--; if(w==0) break;
01167                                    case 3:
01168                                           readPackedSource(rs);
01169                                           rd=*dst;
01170                                           *dst++=alphamaskCombine24(rs, rd)>>8;
01171                                           w--; if(w==0) break;
01172                             }
01173                             wdst=(CARD32 *)dst;
01174                             while (w>3)
01175                             {
01176                                    /* FIXME: write a special readPackedWord macro, which knows how to
01177                                     * halfword combine
01178                                     */
01179 
01180 #if IMAGE_BYTE_ORDER == LSBFirst
01181                                    rd=*wdst;
01182                                    readPackedSource(nd);
01183                                    readPackedSource(rs);
01184                                    nd|=rs<<8;
01185                                    readPackedSource(rs);
01186                                    nd|=rs<<16;
01187                                    readPackedSource(rs);
01188                                    nd|=rs<<24;
01189 #else
01190                                    readPackedSource(nd);
01191                                    nd<<=24;
01192                                    readPackedSource(rs);
01193                                    nd|=rs<<16;
01194                                    readPackedSource(rs);
01195                                    nd|=rs<<8;
01196                                    readPackedSource(rs);
01197                                    nd|=rs;
01198 #endif
01199                                    inOver0888(maskAlpha, nd, rd, *wdst++)
01200                                    w-=4;
01201                             }
01202                             dst=(CARD8 *)wdst;
01203                             switch(w)
01204                             {
01205                                    case 3:
01206                                           readPackedSource(rs);
01207                                           rd=*dst;
01208                                           *dst++=alphamaskCombine24(rs, rd)>>8;
01209                                    case 2:
01210                                           readPackedSource(rs);
01211                                           rd=*dst;
01212                                           *dst++=alphamaskCombine24(rs, rd)>>8;
01213                                    case 1:
01214                                           readPackedSource(rs);
01215                                           rd=*dst;
01216                                           *dst++=alphamaskCombine24(rs, rd)>>8;
01217                             }
01218                      }
01219               }
01220               else
01221               {
01222                      while (height--)
01223                      {
01224                             idst=dst = dstLine;
01225                             dstLine += dstStride;
01226                             src = srcLine;
01227                             srcLine += srcStride;
01228                             w = width*3;
01229                             /* get to word aligned */
01230                             switch(!(long)src&3)
01231                             {
01232                                    case 1:
01233                                           rd=alphamaskCombine24(*src++, *dst)>>8;
01234                                           *dst++=rd;
01235                                           w--; if(w==0) break;
01236                                    case 2:
01237                                           rd=alphamaskCombine24(*src++, *dst)>>8;
01238                                           *dst++=rd;
01239                                           w--; if(w==0) break;
01240                                    case 3:
01241                                           rd=alphamaskCombine24(*src++, *dst)>>8;
01242                                           *dst++=rd;
01243                                           w--; if(w==0) break;
01244                             }
01245                             wsrc=(CARD32 *)src;
01246                             widst=(CARD32 *)dst;
01247 
01248                             while(w>3)
01249                             {
01250                                    rs = *wsrc++;
01251                                    rd = *widst;
01252                                    inOver0888(maskAlpha, rs, rd, *widst++);
01253                                    w-=4;
01254                             }
01255                             src=(CARD8 *)wsrc;
01256                             dst=(CARD8 *)widst;
01257                             switch(w)
01258                             {
01259                                    case 3:
01260                                           rd=alphamaskCombine24(*src++, *dst)>>8;
01261                                           *dst++=rd;
01262                                    case 2:
01263                                           rd=alphamaskCombine24(*src++, *dst)>>8;
01264                                           *dst++=rd;
01265                                    case 1:
01266                                           rd=alphamaskCombine24(*src++, *dst)>>8;
01267                                           *dst++=rd;
01268                             }
01269                      }
01270               }
01271        }
01272 }
01273 
01274 /*
01275  * Simple bitblt
01276  */
01277 
01278 static void
01279 fbCompositeSrcSrc_nxn  (pixman_operator_t op,
01280                      PicturePtr pSrc,
01281                      PicturePtr pMask,
01282                      PicturePtr pDst,
01283                      INT16      xSrc,
01284                      INT16      ySrc,
01285                      INT16      xMask,
01286                      INT16      yMask,
01287                      INT16      xDst,
01288                      INT16      yDst,
01289                      CARD16     width,
01290                      CARD16     height)
01291 {
01292     FbBits    *dst;
01293     FbBits    *src;
01294     FbStride  dstStride, srcStride;
01295     int              srcXoff, srcYoff;
01296     int              dstXoff, dstYoff;
01297     int              srcBpp;
01298     int              dstBpp;
01299     Bool      reverse = FALSE;
01300     Bool      upsidedown = FALSE;
01301 
01302     fbGetDrawable(pSrc->pDrawable,src,srcStride,srcBpp,srcXoff,srcYoff);
01303     fbGetDrawable(pDst->pDrawable,dst,dstStride,dstBpp,dstXoff,dstYoff);
01304 
01305     fbBlt (src + (ySrc + srcYoff) * srcStride,
01306           srcStride,
01307           (xSrc + srcXoff) * srcBpp,
01308 
01309           dst + (yDst + dstYoff) * dstStride,
01310           dstStride,
01311           (xDst + dstXoff) * dstBpp,
01312 
01313           (width) * dstBpp,
01314           (height),
01315 
01316           GXcopy,
01317           FB_ALLONES,
01318           dstBpp,
01319 
01320           reverse,
01321           upsidedown);
01322 }
01323 
01324 /*
01325  * Solid fill
01326 void
01327 fbCompositeSolidSrc_nxn  (CARD8    op,
01328                        PicturePtr pSrc,
01329                        PicturePtr pMask,
01330                        PicturePtr pDst,
01331                        INT16      xSrc,
01332                        INT16      ySrc,
01333                        INT16      xMask,
01334                        INT16      yMask,
01335                        INT16      xDst,
01336                        INT16      yDst,
01337                        CARD16     width,
01338                        CARD16     height)
01339 {
01340 
01341 }
01342  */
01343 
01344 # define mod(a,b)    ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
01345 
01346 void
01347 pixman_composite (pixman_operator_t       op,
01348             PicturePtr pSrc,
01349             PicturePtr pMask,
01350             PicturePtr pDst,
01351             int      xSrc,
01352             int      ySrc,
01353             int      xMask,
01354             int      yMask,
01355             int      xDst,
01356             int      yDst,
01357             int      width,
01358             int      height)
01359 {
01360     pixman_region16_t           *region;
01361     int                  n;
01362     pixman_box16_t    *pbox;
01363     CompositeFunc   func = NULL;
01364     Bool          srcRepeat = pSrc->pDrawable && pSrc->repeat == RepeatNormal;
01365     Bool          maskRepeat = FALSE;
01366     Bool          srcTransform = pSrc->transform != 0;
01367     Bool          maskTransform = FALSE;
01368     Bool          srcAlphaMap = pSrc->alphaMap != 0;
01369     Bool          maskAlphaMap = FALSE;
01370     Bool          dstAlphaMap = pDst->alphaMap != 0;
01371     int                  x_msk, y_msk, x_src, y_src, x_dst, y_dst;
01372     int                  w, h, w_this, h_this;
01373 
01374 #ifdef USE_MMX
01375     static Bool mmx_setup = FALSE;
01376     if (!mmx_setup) {
01377         fbComposeSetupMMX();
01378         mmx_setup = TRUE;
01379     }
01380 #endif
01381         
01382     xDst += pDst->pDrawable->x;
01383     yDst += pDst->pDrawable->y;
01384     if (pSrc->pDrawable) {
01385         xSrc += pSrc->pDrawable->x;
01386         ySrc += pSrc->pDrawable->y;
01387     }
01388 
01389     if (srcRepeat && srcTransform &&
01390        pSrc->pDrawable->width == 1 &&
01391        pSrc->pDrawable->height == 1)
01392        srcTransform = FALSE;
01393 
01394     if (pMask && pMask->pDrawable)
01395     {
01396        xMask += pMask->pDrawable->x;
01397        yMask += pMask->pDrawable->y;
01398        maskRepeat = pMask->repeat == RepeatNormal;
01399        maskTransform = pMask->transform != 0;
01400 #ifdef PIXMAN_CONVOLUTION
01401        if (pMask->filter == PictFilterConvolution)
01402            maskTransform = TRUE;
01403 #endif
01404 
01405        maskAlphaMap = pMask->alphaMap != 0;
01406 
01407        if (maskRepeat && maskTransform &&
01408            pMask->pDrawable->width == 1 &&
01409            pMask->pDrawable->height == 1)
01410            maskTransform = FALSE;
01411     }
01412 
01413     if (pSrc->pDrawable && (!pMask || pMask->pDrawable)
01414         && !srcTransform && !maskTransform
01415         && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
01416 #ifdef PIXMAN_CONVOLUTION
01417         && (pSrc->filter != PictFilterConvolution)
01418         && (!pMask || pMask->filter != PictFilterConvolution)
01419 #endif
01420         )
01421     switch (op) {
01422     case PIXMAN_OPERATOR_OVER:
01423        if (pMask)
01424        {
01425            if (srcRepeat &&
01426               pSrc->pDrawable->width == 1 &&
01427               pSrc->pDrawable->height == 1)
01428            {
01429               if (PICT_FORMAT_COLOR(pSrc->format_code)) {
01430                   switch (pMask->format_code) {
01431                   case PICT_a8:
01432                      switch (pDst->format_code) {
01433                      case PICT_r5g6b5:
01434                      case PICT_b5g6r5:
01435 #ifdef USE_MMX
01436                          if (fbHaveMMX())
01437                             func = fbCompositeSolidMask_nx8x0565mmx;
01438                          else
01439 #endif
01440                             func = fbCompositeSolidMask_nx8x0565;
01441                          break;
01442                      case PICT_r8g8b8:
01443                      case PICT_b8g8r8:
01444                          func = fbCompositeSolidMask_nx8x0888;
01445                          break;
01446                      case PICT_a8r8g8b8:
01447                      case PICT_x8r8g8b8:
01448                      case PICT_a8b8g8r8:
01449                      case PICT_x8b8g8r8:
01450 #ifdef USE_MMX
01451                          if (fbHaveMMX())
01452                             func = fbCompositeSolidMask_nx8x8888mmx;
01453                          else
01454 #endif
01455                             func = fbCompositeSolidMask_nx8x8888;
01456                          break;
01457                      }
01458                      break;
01459                   case PICT_a8r8g8b8:
01460                      if (pMask->componentAlpha) {
01461                          switch (pDst->format_code) {
01462                          case PICT_a8r8g8b8:
01463                          case PICT_x8r8g8b8:
01464 #ifdef USE_MMX
01465                             if (fbHaveMMX())
01466                                 func = fbCompositeSolidMask_nx8888x8888Cmmx;
01467                             else
01468 #endif
01469                                 func = fbCompositeSolidMask_nx8888x8888C;
01470                             break;
01471                          case PICT_r5g6b5:
01472 #ifdef USE_MMX
01473                             if (fbHaveMMX())
01474                                 func = fbCompositeSolidMask_nx8888x0565Cmmx;
01475                             else
01476 #endif
01477                                 func = fbCompositeSolidMask_nx8888x0565C;
01478                             break;
01479                          }
01480                      }
01481                      else
01482                      {
01483                          switch (pDst->format_code) {
01484                          case PICT_r5g6b5:
01485                             func = fbCompositeSolidMask_nx8888x0565;
01486                             break;
01487                          }
01488                      }
01489                      break;
01490                   case PICT_a8b8g8r8:
01491                      if (pMask->componentAlpha) {
01492                          switch (pDst->format_code) {
01493                          case PICT_a8b8g8r8:
01494                          case PICT_x8b8g8r8:
01495 #ifdef USE_MMX
01496                             if (fbHaveMMX())
01497                                 func = fbCompositeSolidMask_nx8888x8888Cmmx;
01498                             else
01499 #endif
01500                                 func = fbCompositeSolidMask_nx8888x8888C;
01501                             break;
01502                          case PICT_b5g6r5:
01503 #ifdef USE_MMX
01504                             if (fbHaveMMX())
01505                                 func = fbCompositeSolidMask_nx8888x0565Cmmx;
01506                             else
01507 #endif
01508                                 func = fbCompositeSolidMask_nx8888x0565C;
01509                             break;
01510                          }
01511                      }
01512                      else
01513                      {
01514                          switch (pDst->format_code) {
01515                          case PICT_b5g6r5:
01516                             func = fbCompositeSolidMask_nx8888x0565;
01517                             break;
01518                          }
01519                      }
01520                      break;
01521                   case PICT_a1:
01522                      switch (pDst->format_code) {
01523                      case PICT_r5g6b5:
01524                      case PICT_b5g6r5:
01525                      case PICT_r8g8b8:
01526                      case PICT_b8g8r8:
01527                      case PICT_a8r8g8b8:
01528                      case PICT_x8r8g8b8:
01529                      case PICT_a8b8g8r8:
01530                      case PICT_x8b8g8r8:
01531                          func = fbCompositeSolidMask_nx1xn;
01532                          break;
01533                      }
01534                   }
01535               }
01536               if (func != pixman_compositeGeneral)
01537                   srcRepeat = FALSE;
01538            }
01539            else /* has mask and non-repeating source */
01540            {
01541               if (pSrc->pDrawable == pMask->pDrawable &&
01542                   xSrc == xMask && ySrc == yMask &&
01543                   !pMask->componentAlpha)
01544               {
01545                   /* source == mask: non-premultiplied data */
01546                   switch (pSrc->format_code) {
01547                   case PICT_x8b8g8r8:
01548                      switch (pMask->format_code) {
01549                      case PICT_a8r8g8b8:
01550                      case PICT_a8b8g8r8:
01551                          switch (pDst->format_code) {
01552                          case PICT_a8r8g8b8:
01553                          case PICT_x8r8g8b8:
01554 #ifdef USE_MMX
01555                             if (fbHaveMMX())
01556                                 func = fbCompositeSrc_8888RevNPx8888mmx;
01557 #endif
01558                             break;
01559                          case PICT_r5g6b5:
01560 #ifdef USE_MMX
01561                             if (fbHaveMMX())
01562                                 func = fbCompositeSrc_8888RevNPx0565mmx;
01563 #endif
01564                             break;
01565                          }
01566                          break;
01567                      }
01568                      break;
01569                   case PICT_x8r8g8b8:
01570                      switch (pMask->format_code) {
01571                      case PICT_a8r8g8b8:
01572                      case PICT_a8b8g8r8:
01573                          switch (pDst->format_code) {
01574                          case PICT_a8b8g8r8:
01575                          case PICT_x8b8g8r8:
01576 #ifdef USE_MMX
01577                             if (fbHaveMMX())
01578                                 func = fbCompositeSrc_8888RevNPx8888mmx;
01579 #endif
01580                             break;
01581                          case PICT_r5g6b5:
01582 #ifdef USE_MMX
01583                             if (fbHaveMMX())
01584                                 func = fbCompositeSrc_8888RevNPx0565mmx;
01585 #endif
01586                             break;
01587                          }
01588                          break;
01589                      }
01590                      break;
01591                   }
01592                   break;
01593               }
01594               else
01595               {
01596                   /* non-repeating source, repeating mask => translucent window */
01597                   if (maskRepeat &&
01598                      pMask->pDrawable->width == 1 &&
01599                      pMask->pDrawable->height == 1)
01600                   {
01601                      switch (pSrc->format_code) {
01602                      case PICT_r5g6b5:
01603                      case PICT_b5g6r5:
01604                          if (pDst->format_code == pSrc->format_code)
01605                             func = fbCompositeTrans_0565xnx0565;
01606                          break;
01607                      case PICT_r8g8b8:
01608                      case PICT_b8g8r8:
01609                          if (pDst->format_code == pSrc->format_code)
01610                             func = fbCompositeTrans_0888xnx0888;
01611                          break;
01612 #ifdef USE_MMX
01613                      case PICT_x8r8g8b8:
01614                      case PICT_x8b8g8r8:
01615                          if (pDst->format_code == pSrc->format_code &&
01616                             pMask->format_code == PICT_a8 && fbHaveMMX())
01617                             func = fbCompositeSrc_x888x8x8888mmx;
01618                          break;
01619 #if 0 /* This case fails rendercheck for me */
01620                      case PICT_a8r8g8b8:
01621                          if ((pDst->format == PICT_a8r8g8b8 ||
01622                              pDst->format == PICT_x8r8g8b8) &&
01623                             pMask->format == PICT_a8 && fbHaveMMX())
01624                             func = fbCompositeSrc_8888x8x8888mmx;
01625                          break;
01626 #endif
01627                      case PICT_a8b8g8r8:
01628                          if ((pDst->format_code == PICT_a8b8g8r8 ||
01629                              pDst->format_code == PICT_x8b8g8r8) &&
01630                             pMask->format_code == PICT_a8 && fbHaveMMX())
01631                             func = fbCompositeSrc_8888x8x8888mmx;
01632                          break;
01633 #endif
01634                      }
01635 
01636                         if (func != pixman_compositeGeneral)
01637                          maskRepeat = FALSE;
01638                   }
01639               }
01640            }
01641        }
01642        else /* no mask */
01643        {
01644            if (srcRepeat &&
01645               pSrc->pDrawable->width == 1 &&
01646               pSrc->pDrawable->height == 1)
01647            {
01648               /* no mask and repeating source */
01649               switch (pSrc->format_code) {
01650               case PICT_a8r8g8b8:
01651                   switch (pDst->format_code) {
01652                   case PICT_a8r8g8b8:
01653                   case PICT_x8r8g8b8:
01654 #ifdef USE_MMX
01655                      if (fbHaveMMX())
01656                      {
01657                          srcRepeat = FALSE;
01658                          func = fbCompositeSolid_nx8888mmx;
01659                      }
01660 #endif
01661                      break;
01662                   case PICT_r5g6b5:
01663 #ifdef USE_MMX
01664                      if (fbHaveMMX())
01665                      {
01666                          srcRepeat = FALSE;
01667                          func = fbCompositeSolid_nx0565mmx;
01668                      }
01669 #endif
01670                      break;
01671                   }
01672                   break;
01673               }
01674            }
01675            else
01676            {
01677               /*
01678                * Formats without alpha bits are just Copy with Over
01679                */
01680               if (pSrc->format_code == pDst->format_code && !PICT_FORMAT_A(pSrc->format_code))
01681               {
01682 #ifdef USE_MMX
01683                      if (fbHaveMMX() &&
01684                          (pSrc->format_code == PICT_x8r8g8b8 || pSrc->format_code == PICT_x8b8g8r8))
01685                          func = fbCompositeCopyAreammx;
01686                      else
01687 #endif
01688                          func = fbCompositeSrcSrc_nxn;
01689               }
01690               else switch (pSrc->format_code) {
01691               case PICT_a8r8g8b8:
01692                   switch (pDst->format_code) {
01693                   case PICT_a8r8g8b8:
01694                   case PICT_x8r8g8b8:
01695 #ifdef USE_MMX
01696                      if (fbHaveMMX())
01697                          func = fbCompositeSrc_8888x8888mmx;
01698                      else
01699 #endif
01700                          func = fbCompositeSrc_8888x8888;
01701                      break;
01702                   case PICT_r8g8b8:
01703                      func = fbCompositeSrc_8888x0888;
01704                      break;
01705                   case PICT_r5g6b5:
01706                      func = fbCompositeSrc_8888x0565;
01707                      break;
01708                   }
01709                   break;
01710               case PICT_a8b8g8r8:
01711                   switch (pDst->format_code) {
01712                   case PICT_a8b8g8r8:
01713                   case PICT_x8b8g8r8:
01714 #ifdef USE_MMX
01715                      if (fbHaveMMX())
01716                          func = fbCompositeSrc_8888x8888mmx;
01717                      else
01718 #endif
01719                          func = fbCompositeSrc_8888x8888;
01720                      break;
01721                   case PICT_b8g8r8:
01722                      func = fbCompositeSrc_8888x0888;
01723                      break;
01724                   case PICT_b5g6r5:
01725                      func = fbCompositeSrc_8888x0565;
01726                      break;
01727                   }
01728                   break;
01729               }
01730            }
01731        }
01732        break;
01733     case PIXMAN_OPERATOR_ADD:
01734        if (pMask == 0)
01735        {
01736            switch (pSrc->format_code) {
01737            case PICT_a8r8g8b8:
01738               switch (pDst->format_code) {
01739               case PICT_a8r8g8b8:
01740 #ifdef USE_MMX
01741                   if (fbHaveMMX())
01742                      func = fbCompositeSrcAdd_8888x8888mmx;
01743                   else
01744 #endif
01745                      func = fbCompositeSrcAdd_8888x8888;
01746                   break;
01747               }
01748               break;
01749            case PICT_a8b8g8r8:
01750               switch (pDst->format_code) {
01751               case PICT_a8b8g8r8:
01752 #ifdef USE_MMX
01753                   if (fbHaveMMX())
01754                      func = fbCompositeSrcAdd_8888x8888mmx;
01755                   else
01756 #endif
01757                      func = fbCompositeSrcAdd_8888x8888;
01758                   break;
01759               }
01760               break;
01761            case PICT_a8:
01762               switch (pDst->format_code) {
01763               case PICT_a8:
01764 #ifdef USE_MMX
01765                   if (fbHaveMMX())
01766                      func = fbCompositeSrcAdd_8000x8000mmx;
01767                   else
01768 #endif
01769                      func = fbCompositeSrcAdd_8000x8000;
01770                   break;
01771               }
01772               break;
01773            case PICT_a1:
01774               switch (pDst->format_code) {
01775               case PICT_a1:
01776                   func = fbCompositeSrcAdd_1000x1000;
01777                   break;
01778               }
01779               break;
01780            }
01781        }
01782        break;
01783     case PIXMAN_OPERATOR_SRC:
01784        if (pMask)
01785          {
01786 #ifdef USE_MMX
01787            if (srcRepeat &&
01788               pSrc->pDrawable->width == 1 &&
01789               pSrc->pDrawable->height == 1)
01790            {
01791               if (pMask->format_code == PICT_a8)
01792               {
01793                   switch (pDst->format_code) {
01794                   case PICT_a8r8g8b8:
01795                   case PICT_x8r8g8b8:
01796                   case PICT_a8b8g8r8:
01797                   case PICT_x8b8g8r8:
01798                      if (fbHaveMMX())
01799                          func = fbCompositeSolidMaskSrc_nx8x8888mmx;
01800                      break;
01801                   }
01802               }
01803            }
01804 #endif
01805          }
01806        else
01807        {
01808            if (pSrc->format_code == pDst->format_code)
01809            {
01810 #ifdef USE_MMX
01811               if (pSrc->pDrawable != pDst->pDrawable &&
01812                     (PICT_FORMAT_BPP (pSrc->format_code) == 16 ||
01813                      PICT_FORMAT_BPP (pSrc->format_code) == 32))
01814                   func = fbCompositeCopyAreammx;
01815               else
01816 #endif
01817                   func = fbCompositeSrcSrc_nxn;
01818            }
01819        }
01820        break;
01821     }
01822 
01823     if (!func) {
01824         /* no fast path, use the general code */
01825         pixman_compositeGeneral(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
01826         return;
01827     }
01828 
01829     /* if we are transforming, we handle repeats in IcFetch[a]_transform */
01830     if (srcTransform)
01831        srcRepeat = 0;
01832     if (maskTransform)
01833        maskRepeat = 0;
01834 
01835     region = pixman_region_create();
01836     pixman_region_union_rect (region, region, xDst, yDst, width, height);
01837     
01838     if (!FbComputeCompositeRegion (region,
01839                                pSrc,
01840                                pMask,
01841                                pDst,
01842                                xSrc,
01843                                ySrc,
01844                                xMask,
01845                                yMask,
01846                                xDst,
01847                                yDst,
01848                                width,
01849                                height))
01850        return;
01851     
01852     n = pixman_region_num_rects (region);
01853     pbox = pixman_region_rects (region);
01854     while (n--)
01855     {
01856        h = pbox->y2 - pbox->y1;
01857        y_src = pbox->y1 - yDst + ySrc;
01858        y_msk = pbox->y1 - yDst + yMask;
01859        y_dst = pbox->y1;
01860        while (h)
01861        {
01862            h_this = h;
01863            w = pbox->x2 - pbox->x1;
01864            x_src = pbox->x1 - xDst + xSrc;
01865            x_msk = pbox->x1 - xDst + xMask;
01866            x_dst = pbox->x1;
01867            if (maskRepeat)
01868            {
01869               y_msk = mod (y_msk, pMask->pDrawable->height);
01870               if (h_this > pMask->pDrawable->height - y_msk)
01871                   h_this = pMask->pDrawable->height - y_msk;
01872            }
01873            if (srcRepeat)
01874            {
01875               y_src = mod (y_src, pSrc->pDrawable->height);
01876               if (h_this > pSrc->pDrawable->height - y_src)
01877                   h_this = pSrc->pDrawable->height - y_src;
01878            }
01879            while (w)
01880            {
01881               w_this = w;
01882               if (maskRepeat)
01883               {
01884                   x_msk = mod (x_msk, pMask->pDrawable->width);
01885                   if (w_this > pMask->pDrawable->width - x_msk)
01886                      w_this = pMask->pDrawable->width - x_msk;
01887               }
01888               if (srcRepeat)
01889               {
01890                   x_src = mod (x_src, pSrc->pDrawable->width);
01891                   if (w_this > pSrc->pDrawable->width - x_src)
01892                      w_this = pSrc->pDrawable->width - x_src;
01893               }
01894               (*func) (op, pSrc, pMask, pDst,
01895                       x_src, y_src, x_msk, y_msk, x_dst, y_dst,
01896                       w_this, h_this);
01897               w -= w_this;
01898               x_src += w_this;
01899               x_msk += w_this;
01900               x_dst += w_this;
01901            }
01902            h -= h_this;
01903            y_src += h_this;
01904            y_msk += h_this;
01905            y_dst += h_this;
01906        }
01907        pbox++;
01908     }
01909     pixman_region_destroy (region);
01910 }
01911 slim_hidden_def(pixman_composite);
01912 
01913 /* The CPU detection code needs to be in a file not compiled with
01914  * "-mmmx -msse", as gcc would generate CMOV instructions otherwise
01915  * that would lead to SIGILL instructions on old CPUs that don't have
01916  * it.
01917  */
01918 #if defined(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__)
01919 
01920 enum CPUFeatures {
01921     NoFeatures = 0,
01922     MMX = 0x1,
01923     MMX_Extensions = 0x2, 
01924     SSE = 0x6,
01925     SSE2 = 0x8,
01926     CMOV = 0x10
01927 };
01928 
01929 static unsigned int detectCPUFeatures(void) {
01930     unsigned int result;
01931     char vendor[13];
01932     vendor[0] = 0;
01933     vendor[12] = 0;
01934     /* see p. 118 of amd64 instruction set manual Vol3 */
01935     /* We need to be careful about the handling of %ebx and
01936      * %esp here. We can't declare either one as clobbered
01937      * since they are special registers (%ebx is the "PIC
01938      * register" holding an offset to global data, %esp the
01939      * stack pointer), so we need to make sure they have their
01940      * original values when we access the output operands.
01941      */
01942     __asm__ ("pushf\n"
01943              "pop %%eax\n"
01944              "mov %%eax, %%ecx\n"
01945              "xor $0x00200000, %%eax\n"
01946              "push %%eax\n"
01947              "popf\n"
01948              "pushf\n"
01949              "pop %%eax\n"
01950              "mov $0x0, %%edx\n"
01951              "xor %%ecx, %%eax\n"
01952              "jz 1f\n"
01953 
01954              "mov $0x00000000, %%eax\n"
01955             "push %%ebx\n"
01956              "cpuid\n"
01957              "mov %%ebx, %%eax\n"
01958             "pop %%ebx\n"
01959              "mov %%eax, %1\n"
01960              "mov %%edx, %2\n"
01961              "mov %%ecx, %3\n"
01962              "mov $0x00000001, %%eax\n"
01963             "push %%ebx\n"
01964              "cpuid\n"
01965             "pop %%ebx\n"
01966              "1:\n"
01967              "mov %%edx, %0\n"
01968              : "=r" (result), 
01969                "=m" (vendor[0]), 
01970                "=m" (vendor[4]), 
01971                "=m" (vendor[8])
01972              :
01973              : "%eax", "%ecx", "%edx"
01974         );
01975 
01976     unsigned int features = 0;
01977     if (result) {
01978         /* result now contains the standard feature bits */
01979         if (result & (1 << 15))
01980             features |= CMOV;
01981         if (result & (1 << 23))
01982             features |= MMX;
01983         if (result & (1 << 25))
01984             features |= SSE;
01985         if (result & (1 << 26))
01986             features |= SSE2;
01987         if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) {
01988             /* check for AMD MMX extensions */
01989 
01990             unsigned int result;            
01991             __asm__("push %%ebx\n"
01992                     "mov $0x80000000, %%eax\n"
01993                     "cpuid\n"
01994                     "xor %%edx, %%edx\n"
01995                     "cmp $0x1, %%eax\n"
01996                     "jge 1f\n"
01997                     "mov $0x80000001, %%eax\n"
01998                     "cpuid\n"
01999                     "1:\n"
02000                     "pop %%ebx\n"
02001                     "mov %%edx, %0\n"
02002                     : "=r" (result)
02003                     :
02004                     : "%eax", "%ecx", "%edx"
02005                 );
02006             if (result & (1<<22))
02007                 features |= MMX_Extensions;
02008         }
02009     }
02010     return features;
02011 }
02012 
02013 Bool
02014 fbHaveMMX (void)
02015 {
02016     static Bool initialized = FALSE;
02017     static Bool mmx_present;
02018 
02019     if (!initialized)
02020     {
02021         unsigned int features = detectCPUFeatures();
02022        mmx_present = (features & (MMX|MMX_Extensions)) == (MMX|MMX_Extensions);
02023         initialized = TRUE;
02024     }
02025     
02026     return mmx_present;
02027 }
02028 #endif /* USE_MMX && !amd64 */
02029 #endif /* RENDER */