Back to index

lightning-sunbird  0.9+nobinonly
fbcompose.c
Go to the documentation of this file.
00001 /*
00002  * $XdotOrg: xc/programs/Xserver/fb/fbcompose.c,v 1.5 2005/01/13 20:49:21 sandmann Exp $
00003  *
00004  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
00005  *             2005 Lars Knoll & Zack Rusin, Trolltech
00006  *
00007  * Permission to use, copy, modify, distribute, and sell this software and its
00008  * documentation for any purpose is hereby granted without fee, provided that
00009  * the above copyright notice appear in all copies and that both that
00010  * copyright notice and this permission notice appear in supporting
00011  * documentation, and that the name of Keith Packard not be used in
00012  * advertising or publicity pertaining to distribution of the software without
00013  * specific, written prior permission.  Keith Packard makes no
00014  * representations about the suitability of this software for any purpose.  It
00015  * is provided "as is" without express or implied warranty.
00016  *
00017  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
00018  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
00019  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
00020  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00021  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
00022  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
00023  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00024  * SOFTWARE.
00025  */
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029 #include "pixman-xserver-compat.h"
00030 #include "fbpict.h"
00031 
00032 #ifdef RENDER
00033 
00034 #include "pixregionint.h"
00035 
00036 // #define PIXMAN_CONVOLUTION
00037 // #define PIXMAN_GRADIENTS
00038 // #define PIXMAN_INDEXED_FORMATS
00039 
00040 static Bool
00041 PictureTransformPoint3d (pixman_transform_t *transform,
00042                          PictVector *vector)
00043 {
00044     PictVector           result;
00045     int                  i, j;
00046     xFixed_32_32    partial;
00047     xFixed_48_16    v;
00048 
00049     for (j = 0; j < 3; j++)
00050     {
00051        v = 0;
00052        for (i = 0; i < 3; i++)
00053        {
00054            partial = ((xFixed_48_16) transform->matrix[j][i] *
00055                      (xFixed_48_16) vector->vector[i]);
00056            v += partial >> 16;
00057        }
00058        if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
00059            return FALSE;
00060        result.vector[j] = (xFixed) v;
00061     }
00062     if (!result.vector[2])
00063        return FALSE;
00064     *vector = result;
00065     return TRUE;
00066 }
00067 
00068 #define mod(a,b)     ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
00069 
00070 #define SCANLINE_BUFFER_LENGTH 2048
00071 
00072 typedef FASTCALL void (*fetchProc)(const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed);
00073 
00074 /*
00075  * All of the fetch functions
00076  */
00077 
00078 static FASTCALL void
00079 fbFetch_a8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00080 {
00081     memcpy(buffer, (const CARD32 *)bits + x, width*sizeof(CARD32));
00082 }
00083 
00084 static FASTCALL void
00085 fbFetch_x8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00086 {
00087     const CARD32 *pixel = (const CARD32 *)bits + x;
00088     const CARD32 *end = pixel + width;
00089     while (pixel < end) {
00090         *buffer++ = *pixel++ | 0xff000000;
00091     }
00092 }
00093 
00094 static FASTCALL void
00095 fbFetch_a8b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00096 {
00097     const CARD32 *pixel = (CARD32 *)bits + x;
00098     const CARD32 *end = pixel + width;
00099     while (pixel < end) {
00100         *buffer++ =  ((*pixel & 0xff00ff00) |
00101                       ((*pixel >> 16) & 0xff) |
00102                       ((*pixel & 0xff) << 16));
00103         ++pixel;
00104     }
00105 }
00106 
00107 static FASTCALL void
00108 fbFetch_x8b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00109 {
00110     const CARD32 *pixel = (CARD32 *)bits + x;
00111     const CARD32 *end = pixel + width;
00112     while (pixel < end) {
00113         *buffer++ =  0xff000000 |
00114                      ((*pixel & 0x0000ff00) |
00115                       ((*pixel >> 16) & 0xff) |
00116                       ((*pixel & 0xff) << 16));
00117         ++pixel;
00118     }
00119 }
00120 
00121 static FASTCALL void
00122 fbFetch_r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00123 {
00124     const CARD8 *pixel = (const CARD8 *)bits + 3*x;
00125     const CARD8 *end = pixel + 3*width;
00126     while (pixel < end) {
00127         CARD32 b = Fetch24(pixel) | 0xff000000;
00128         pixel += 3;
00129         *buffer++ = b;
00130     }
00131 }
00132 
00133 static FASTCALL void
00134 fbFetch_b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00135 {
00136     const CARD8 *pixel = (const CARD8 *)bits + 3*x;
00137     const CARD8 *end = pixel + 3*width;
00138     while (pixel < end) {
00139         CARD32 b = 0xff000000;
00140 #if IMAGE_BYTE_ORDER == MSBFirst
00141         b |= (*pixel++);
00142         b |= (*pixel++ << 8);
00143         b |= (*pixel++ << 16);
00144 #else
00145         b |= (*pixel++ << 16);
00146         b |= (*pixel++ << 8);
00147         b |= (*pixel++);
00148 #endif
00149     }
00150 }
00151 
00152 static FASTCALL void
00153 fbFetch_r5g6b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00154 {
00155     const CARD16 *pixel = (const CARD16 *)bits + x;
00156     const CARD16 *end = pixel + width;
00157     while (pixel < end) {
00158         CARD32  p = *pixel++;
00159         CARD32 r = (((p) << 3) & 0xf8) | 
00160                    (((p) << 5) & 0xfc00) |
00161                    (((p) << 8) & 0xf80000);
00162         r |= (r >> 5) & 0x70007;
00163         r |= (r >> 6) & 0x300;
00164         *buffer++ = 0xff000000 | r;
00165     }
00166 }
00167 
00168 static FASTCALL void
00169 fbFetch_b5g6r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00170 {
00171     const CARD16 *pixel = (const CARD16 *)bits + x;
00172     const CARD16 *end = pixel + width;
00173     while (pixel < end) {
00174         CARD32  p = *pixel++;
00175         CARD32  r,g,b;
00176 
00177         b = ((p & 0xf800) | ((p & 0xe000) >> 5)) >> 8;
00178         g = ((p & 0x07e0) | ((p & 0x0600) >> 6)) << 5;
00179         r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
00180         *buffer++ = (0xff000000 | r | g | b);
00181     }
00182 }
00183 
00184 static FASTCALL void
00185 fbFetch_a1r5g5b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00186 {
00187     const CARD16 *pixel = (const CARD16 *)bits + x;
00188     const CARD16 *end = pixel + width;
00189     while (pixel < end) {
00190         CARD32  p = *pixel++;
00191         CARD32  r,g,b, a;
00192 
00193         a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24;
00194         r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9;
00195         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
00196         b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2;
00197         *buffer++ = (a | r | g | b);
00198     }
00199 }
00200 
00201 static FASTCALL void
00202 fbFetch_x1r5g5b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00203 {
00204     const CARD16 *pixel = (const CARD16 *)bits + x;
00205     const CARD16 *end = pixel + width;
00206     while (pixel < end) {
00207         CARD32  p = *pixel++;
00208         CARD32  r,g,b;
00209 
00210         r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9;
00211         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
00212         b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2;
00213         *buffer++ = (0xff000000 | r | g | b);
00214     }
00215 }
00216 
00217 static FASTCALL void
00218 fbFetch_a1b5g5r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00219 {
00220     const CARD16 *pixel = (const CARD16 *)bits + x;
00221     const CARD16 *end = pixel + width;
00222     while (pixel < end) {
00223         CARD32  p = *pixel++;
00224         CARD32  r,g,b, a;
00225 
00226         a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24;
00227         b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7;
00228         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
00229         r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
00230         *buffer++ = (a | r | g | b);
00231     }
00232 }
00233 
00234 static FASTCALL void
00235 fbFetch_x1b5g5r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00236 {
00237     const CARD16 *pixel = (const CARD16 *)bits + x;
00238     const CARD16 *end = pixel + width;
00239     while (pixel < end) {
00240         CARD32  p = *pixel++;
00241         CARD32  r,g,b;
00242 
00243         b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7;
00244         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
00245         r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
00246         *buffer++ = (0xff000000 | r | g | b);
00247     }
00248 }
00249 
00250 static FASTCALL void
00251 fbFetch_a4r4g4b4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00252 {
00253     const CARD16 *pixel = (const CARD16 *)bits + x;
00254     const CARD16 *end = pixel + width;
00255     while (pixel < end) {
00256         CARD32  p = *pixel++;
00257         CARD32  r,g,b, a;
00258 
00259         a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16;
00260         r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
00261         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
00262         b = ((p & 0x000f) | ((p & 0x000f) << 4));
00263         *buffer++ = (a | r | g | b);
00264     }
00265 }
00266 
00267 static FASTCALL void
00268 fbFetch_x4r4g4b4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00269 {
00270     const CARD16 *pixel = (const CARD16 *)bits + x;
00271     const CARD16 *end = pixel + width;
00272     while (pixel < end) {
00273         CARD32  p = *pixel++;
00274         CARD32  r,g,b;
00275 
00276         r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
00277         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
00278         b = ((p & 0x000f) | ((p & 0x000f) << 4));
00279         *buffer++ = (0xff000000 | r | g | b);
00280     }
00281 }
00282 
00283 static FASTCALL void
00284 fbFetch_a4b4g4r4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00285 {
00286     const CARD16 *pixel = (const CARD16 *)bits + x;
00287     const CARD16 *end = pixel + width;
00288     while (pixel < end) {
00289         CARD32  p = *pixel++;
00290         CARD32  r,g,b, a;
00291 
00292         a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16;
00293         b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
00294         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
00295         r = ((p & 0x000f) | ((p & 0x000f) << 4));
00296         *buffer++ = (a | r | g | b);
00297     }
00298 }
00299 
00300 static FASTCALL void
00301 fbFetch_x4b4g4r4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00302 {
00303     const CARD16 *pixel = (const CARD16 *)bits + x;
00304     const CARD16 *end = pixel + width;
00305     while (pixel < end) {
00306         CARD32  p = *pixel++;
00307         CARD32  r,g,b;
00308 
00309         b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
00310         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
00311         r = ((p & 0x000f) | ((p & 0x000f) << 4));
00312         *buffer++ = (0xff000000 | r | g | b);
00313     }
00314 }
00315 
00316 static FASTCALL void
00317 fbFetch_a8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00318 {
00319     const CARD8 *pixel = (const CARD8 *)bits + x;
00320     const CARD8 *end = pixel + width;
00321     while (pixel < end) {
00322         *buffer++ = (*pixel++) << 24;
00323     }
00324 }
00325 
00326 static FASTCALL void
00327 fbFetch_r3g3b2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00328 {
00329     const CARD8 *pixel = (const CARD8 *)bits + x;
00330     const CARD8 *end = pixel + width;
00331     while (pixel < end) {
00332         CARD32  p = *pixel++;
00333         CARD32  r,g,b;
00334 
00335         r = ((p & 0xe0) | ((p & 0xe0) >> 3) | ((p & 0xc0) >> 6)) << 16;
00336         g = ((p & 0x1c) | ((p & 0x18) >> 3) | ((p & 0x1c) << 3)) << 8;
00337         b = (((p & 0x03)     ) |
00338              ((p & 0x03) << 2) |
00339              ((p & 0x03) << 4) |
00340              ((p & 0x03) << 6));
00341         *buffer++ = (0xff000000 | r | g | b);
00342     }
00343 }
00344 
00345 static FASTCALL void
00346 fbFetch_b2g3r3 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00347 {
00348     const CARD8 *pixel = (const CARD8 *)bits + x;
00349     const CARD8 *end = pixel + width;
00350     while (pixel < end) {
00351         CARD32  p = *pixel++;
00352         CARD32  r,g,b;
00353 
00354         b = (((p & 0xc0)     ) |
00355              ((p & 0xc0) >> 2) |
00356              ((p & 0xc0) >> 4) |
00357              ((p & 0xc0) >> 6));
00358         g = ((p & 0x38) | ((p & 0x38) >> 3) | ((p & 0x30) << 2)) << 8;
00359         r = (((p & 0x07)     ) |
00360              ((p & 0x07) << 3) |
00361              ((p & 0x06) << 6)) << 16;
00362         *buffer++ = (0xff000000 | r | g | b);
00363     }
00364 }
00365 
00366 static FASTCALL void
00367 fbFetch_a2r2g2b2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00368 {
00369     const CARD8 *pixel = (const CARD8 *)bits + x;
00370     const CARD8 *end = pixel + width;
00371     while (pixel < end) {
00372         CARD32  p = *pixel++;
00373         CARD32   a,r,g,b;
00374 
00375         a = ((p & 0xc0) * 0x55) << 18;
00376         r = ((p & 0x30) * 0x55) << 12;
00377         g = ((p & 0x0c) * 0x55) << 6;
00378         b = ((p & 0x03) * 0x55);
00379         *buffer++ = a|r|g|b;
00380        }
00381 }
00382 
00383 static FASTCALL void
00384 fbFetch_a2b2g2r2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00385 {
00386     const CARD8 *pixel = (const CARD8 *)bits + x;
00387     const CARD8 *end = pixel + width;
00388     while (pixel < end) {
00389         CARD32  p = *pixel++;
00390         CARD32   a,r,g,b;
00391 
00392         a = ((p & 0xc0) * 0x55) << 18;
00393         b = ((p & 0x30) * 0x55) >> 6;
00394         g = ((p & 0x0c) * 0x55) << 6;
00395         r = ((p & 0x03) * 0x55) << 16;
00396         *buffer++ = a|r|g|b;
00397     }
00398 }
00399 
00400 static FASTCALL void
00401 fbFetch_c8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00402 {
00403     const CARD8 *pixel = (const CARD8 *)bits + x;
00404     const CARD8 *end = pixel + width;
00405     while (pixel < end) {
00406         CARD32  p = *pixel++;
00407         *buffer++ = indexed->rgba[p];
00408     }
00409 }
00410 
00411 #define Fetch8(l,o)    (((CARD8 *) (l))[(o) >> 2])
00412 #if IMAGE_BYTE_ORDER == MSBFirst
00413 #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4)
00414 #else
00415 #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf)
00416 #endif
00417 
00418 static FASTCALL void
00419 fbFetch_a4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00420 {
00421     int i;
00422     for (i = 0; i < width; ++i) {
00423         CARD32  p = Fetch4(bits, i + x);
00424 
00425         p |= p << 4;
00426         *buffer++ = p << 24;
00427     }
00428 }
00429 
00430 static FASTCALL void
00431 fbFetch_r1g2b1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00432 {
00433     int i;
00434     for (i = 0; i < width; ++i) {
00435         CARD32  p = Fetch4(bits, i + x);
00436         CARD32  r,g,b;
00437 
00438         r = ((p & 0x8) * 0xff) << 13;
00439         g = ((p & 0x6) * 0x55) << 7;
00440         b = ((p & 0x1) * 0xff);
00441         *buffer++ = 0xff000000|r|g|b;
00442     }
00443 }
00444 
00445 static FASTCALL void
00446 fbFetch_b1g2r1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00447 {
00448     int i;
00449     for (i = 0; i < width; ++i) {
00450         CARD32  p = Fetch4(bits, i + x);
00451         CARD32  r,g,b;
00452 
00453         b = ((p & 0x8) * 0xff) >> 3;
00454         g = ((p & 0x6) * 0x55) << 7;
00455         r = ((p & 0x1) * 0xff) << 16;
00456         *buffer++ = 0xff000000|r|g|b;
00457     }
00458 }
00459 
00460 static FASTCALL void
00461 fbFetch_a1r1g1b1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00462 {
00463     int i;
00464     for (i = 0; i < width; ++i) {
00465         CARD32  p = Fetch4(bits, i + x);
00466         CARD32  a,r,g,b;
00467 
00468         a = ((p & 0x8) * 0xff) << 21;
00469         r = ((p & 0x4) * 0xff) << 14;
00470         g = ((p & 0x2) * 0xff) << 7;
00471         b = ((p & 0x1) * 0xff);
00472         *buffer++ = a|r|g|b;
00473     }
00474 }
00475 
00476 static FASTCALL void
00477 fbFetch_a1b1g1r1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00478 {
00479     int i;
00480     for (i = 0; i < width; ++i) {
00481         CARD32  p = Fetch4(bits, i + x);
00482         CARD32  a,r,g,b;
00483 
00484         a = ((p & 0x8) * 0xff) << 21;
00485         r = ((p & 0x4) * 0xff) >> 3;
00486         g = ((p & 0x2) * 0xff) << 7;
00487         b = ((p & 0x1) * 0xff) << 16;
00488         *buffer++ = a|r|g|b;
00489     }
00490 }
00491 
00492 static FASTCALL void
00493 fbFetch_c4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00494 {
00495     int i;
00496     for (i = 0; i < width; ++i) {
00497         CARD32  p = Fetch4(bits, i + x);
00498 
00499         *buffer++ = indexed->rgba[p];
00500     }
00501 }
00502 
00503 
00504 static FASTCALL void
00505 fbFetch_a1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00506 {
00507     int i;
00508     for (i = 0; i < width; ++i) {
00509         CARD32  p = ((CARD32 *)bits)[(i + x) >> 5];
00510         CARD32  a;
00511 #if BITMAP_BIT_ORDER == MSBFirst
00512         a = p >> (0x1f - ((i+x) & 0x1f));
00513 #else
00514         a = p >> ((i+x) & 0x1f);
00515 #endif
00516         a = a & 1;
00517         a |= a << 1;
00518         a |= a << 2;
00519         a |= a << 4;
00520         *buffer++ = a << 24;
00521     }
00522 }
00523 
00524 static FASTCALL void
00525 fbFetch_g1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
00526 {
00527     int i;
00528     for (i = 0; i < width; ++i) {
00529         CARD32  p = ((CARD32 *)bits)[(i+x) >> 5];
00530         CARD32 a;
00531 #if BITMAP_BIT_ORDER == MSBFirst
00532         a = p >> (0x1f - ((i+x) & 0x1f));
00533 #else
00534         a = p >> ((i+x) & 0x1f);
00535 #endif
00536         a = a & 1;
00537         *buffer++ = indexed->rgba[a];
00538     }
00539 }
00540 
00541 static fetchProc fetchProcForPicture (PicturePtr pict)
00542 {
00543     switch(pict->format_code) {
00544     case PICT_a8r8g8b8: return fbFetch_a8r8g8b8;
00545     case PICT_x8r8g8b8: return fbFetch_x8r8g8b8;
00546     case PICT_a8b8g8r8: return fbFetch_a8b8g8r8;
00547     case PICT_x8b8g8r8: return fbFetch_x8b8g8r8;
00548 
00549         /* 24bpp formats */
00550     case PICT_r8g8b8: return fbFetch_r8g8b8;
00551     case PICT_b8g8r8: return fbFetch_b8g8r8;
00552 
00553         /* 16bpp formats */
00554     case PICT_r5g6b5: return fbFetch_r5g6b5;
00555     case PICT_b5g6r5: return fbFetch_b5g6r5;
00556 
00557     case PICT_a1r5g5b5: return fbFetch_a1r5g5b5;
00558     case PICT_x1r5g5b5: return fbFetch_x1r5g5b5;
00559     case PICT_a1b5g5r5: return fbFetch_a1b5g5r5;
00560     case PICT_x1b5g5r5: return fbFetch_x1b5g5r5;
00561     case PICT_a4r4g4b4: return fbFetch_a4r4g4b4;
00562     case PICT_x4r4g4b4: return fbFetch_x4r4g4b4;
00563     case PICT_a4b4g4r4: return fbFetch_a4b4g4r4;
00564     case PICT_x4b4g4r4: return fbFetch_x4b4g4r4;
00565 
00566         /* 8bpp formats */
00567     case PICT_a8: return  fbFetch_a8;
00568     case PICT_r3g3b2: return fbFetch_r3g3b2;
00569     case PICT_b2g3r3: return fbFetch_b2g3r3;
00570     case PICT_a2r2g2b2: return fbFetch_a2r2g2b2;
00571     case PICT_a2b2g2r2: return fbFetch_a2b2g2r2;
00572     case PICT_c8: return  fbFetch_c8;
00573     case PICT_g8: return  fbFetch_c8;
00574 
00575         /* 4bpp formats */
00576     case PICT_a4: return  fbFetch_a4;
00577     case PICT_r1g2b1: return fbFetch_r1g2b1;
00578     case PICT_b1g2r1: return fbFetch_b1g2r1;
00579     case PICT_a1r1g1b1: return fbFetch_a1r1g1b1;
00580     case PICT_a1b1g1r1: return fbFetch_a1b1g1r1;
00581     case PICT_c4: return  fbFetch_c4;
00582     case PICT_g4: return  fbFetch_c4;
00583 
00584         /* 1bpp formats */
00585     case PICT_a1: return  fbFetch_a1;
00586     case PICT_g1: return  fbFetch_g1;
00587     default:
00588         return NULL;
00589     }
00590 }
00591 
00592 /*
00593  * Pixel wise fetching
00594  */
00595 
00596 typedef FASTCALL CARD32 (*fetchPixelProc)(const FbBits *bits, int offset, miIndexedPtr indexed);
00597 
00598 static FASTCALL CARD32
00599 fbFetchPixel_a8r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00600 {
00601     return ((CARD32 *)bits)[offset];
00602 }
00603 
00604 static FASTCALL CARD32
00605 fbFetchPixel_x8r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00606 {
00607     return ((CARD32 *)bits)[offset] | 0xff000000;
00608 }
00609 
00610 static FASTCALL CARD32
00611 fbFetchPixel_a8b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00612 {
00613     CARD32  pixel = ((CARD32 *)bits)[offset];
00614 
00615     return ((pixel & 0xff000000) |
00616            ((pixel >> 16) & 0xff) |
00617            (pixel & 0x0000ff00) |
00618            ((pixel & 0xff) << 16));
00619 }
00620 
00621 static FASTCALL CARD32
00622 fbFetchPixel_x8b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00623 {
00624     CARD32  pixel = ((CARD32 *)bits)[offset];
00625 
00626     return ((0xff000000) |
00627            ((pixel >> 16) & 0xff) |
00628            (pixel & 0x0000ff00) |
00629            ((pixel & 0xff) << 16));
00630 }
00631 
00632 static FASTCALL CARD32
00633 fbFetchPixel_r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00634 {
00635     CARD8   *pixel = ((CARD8 *) bits) + (offset*3);
00636 #if IMAGE_BYTE_ORDER == MSBFirst
00637     return (0xff000000 |
00638            (pixel[0] << 16) |
00639            (pixel[1] << 8) |
00640            (pixel[2]));
00641 #else
00642     return (0xff000000 |
00643             (pixel[2] << 16) |
00644             (pixel[1] << 8) |
00645             (pixel[0]));
00646 #endif
00647 }
00648 
00649 static FASTCALL CARD32
00650 fbFetchPixel_b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00651 {
00652     CARD8   *pixel = ((CARD8 *) bits) + (offset*3);
00653 #if IMAGE_BYTE_ORDER == MSBFirst
00654     return (0xff000000 |
00655            (pixel[2] << 16) |
00656            (pixel[1] << 8) |
00657            (pixel[0]));
00658 #else
00659     return (0xff000000 |
00660            (pixel[0] << 16) |
00661            (pixel[1] << 8) |
00662            (pixel[2]));
00663 #endif
00664 }
00665 
00666 static FASTCALL CARD32
00667 fbFetchPixel_r5g6b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
00668 {
00669     CARD32  pixel = ((CARD16 *) bits)[offset];
00670     CARD32  r,g,b;
00671 
00672     r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8;
00673     g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5;
00674     b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
00675     return (0xff000000 | r | g | b);
00676 }
00677 
00678 static FASTCALL CARD32
00679 fbFetchPixel_b5g6r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
00680 {
00681     CARD32  pixel = ((CARD16 *) bits)[offset];
00682     CARD32  r,g,b;
00683 
00684     b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8;
00685     g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5;
00686     r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
00687     return (0xff000000 | r | g | b);
00688 }
00689 
00690 static FASTCALL CARD32
00691 fbFetchPixel_a1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
00692 {
00693     CARD32  pixel = ((CARD16 *) bits)[offset];
00694     CARD32  a,r,g,b;
00695 
00696     a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24;
00697     r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9;
00698     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
00699     b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
00700     return (a | r | g | b);
00701 }
00702 
00703 static FASTCALL CARD32
00704 fbFetchPixel_x1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
00705 {
00706     CARD32  pixel = ((CARD16 *) bits)[offset];
00707     CARD32  r,g,b;
00708 
00709     r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9;
00710     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
00711     b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
00712     return (0xff000000 | r | g | b);
00713 }
00714 
00715 static FASTCALL CARD32
00716 fbFetchPixel_a1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
00717 {
00718     CARD32  pixel = ((CARD16 *) bits)[offset];
00719     CARD32  a,r,g,b;
00720 
00721     a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24;
00722     b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7;
00723     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
00724     r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
00725     return (a | r | g | b);
00726 }
00727 
00728 static FASTCALL CARD32
00729 fbFetchPixel_x1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
00730 {
00731     CARD32  pixel = ((CARD16 *) bits)[offset];
00732     CARD32  r,g,b;
00733 
00734     b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7;
00735     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
00736     r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
00737     return (0xff000000 | r | g | b);
00738 }
00739 
00740 static FASTCALL CARD32
00741 fbFetchPixel_a4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed)
00742 {
00743     CARD32  pixel = ((CARD16 *) bits)[offset];
00744     CARD32  a,r,g,b;
00745 
00746     a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16;
00747     r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
00748     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
00749     b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
00750     return (a | r | g | b);
00751 }
00752 
00753 static FASTCALL CARD32
00754 fbFetchPixel_x4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed)
00755 {
00756     CARD32  pixel = ((CARD16 *) bits)[offset];
00757     CARD32  r,g,b;
00758 
00759     r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
00760     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
00761     b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
00762     return (0xff000000 | r | g | b);
00763 }
00764 
00765 static FASTCALL CARD32
00766 fbFetchPixel_a4b4g4r4 (const FbBits *bits, int offset, miIndexedPtr indexed)
00767 {
00768     CARD32  pixel = ((CARD16 *) bits)[offset];
00769     CARD32  a,r,g,b;
00770 
00771     a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16;
00772     b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
00773     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
00774     r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
00775     return (a | r | g | b);
00776 }
00777 
00778 static FASTCALL CARD32
00779 fbFetchPixel_x4b4g4r4 (const FbBits *bits, int offset, miIndexedPtr indexed)
00780 {
00781     CARD32  pixel = ((CARD16 *) bits)[offset];
00782     CARD32  r,g,b;
00783 
00784     b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
00785     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
00786     r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
00787     return (0xff000000 | r | g | b);
00788 }
00789 
00790 static FASTCALL CARD32
00791 fbFetchPixel_a8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00792 {
00793     CARD32   pixel = ((CARD8 *) bits)[offset];
00794 
00795     return pixel << 24;
00796 }
00797 
00798 static FASTCALL CARD32
00799 fbFetchPixel_r3g3b2 (const FbBits *bits, int offset, miIndexedPtr indexed)
00800 {
00801     CARD32   pixel = ((CARD8 *) bits)[offset];
00802     CARD32  r,g,b;
00803 
00804     r = ((pixel & 0xe0) | ((pixel & 0xe0) >> 3) | ((pixel & 0xc0) >> 6)) << 16;
00805     g = ((pixel & 0x1c) | ((pixel & 0x18) >> 3) | ((pixel & 0x1c) << 3)) << 8;
00806     b = (((pixel & 0x03)     ) |
00807         ((pixel & 0x03) << 2) |
00808         ((pixel & 0x03) << 4) |
00809         ((pixel & 0x03) << 6));
00810     return (0xff000000 | r | g | b);
00811 }
00812 
00813 static FASTCALL CARD32
00814 fbFetchPixel_b2g3r3 (const FbBits *bits, int offset, miIndexedPtr indexed)
00815 {
00816     CARD32   pixel = ((CARD8 *) bits)[offset];
00817     CARD32  r,g,b;
00818 
00819     b = (((pixel & 0xc0)     ) |
00820         ((pixel & 0xc0) >> 2) |
00821         ((pixel & 0xc0) >> 4) |
00822         ((pixel & 0xc0) >> 6));
00823     g = ((pixel & 0x38) | ((pixel & 0x38) >> 3) | ((pixel & 0x30) << 2)) << 8;
00824     r = (((pixel & 0x07)     ) |
00825         ((pixel & 0x07) << 3) |
00826         ((pixel & 0x06) << 6)) << 16;
00827     return (0xff000000 | r | g | b);
00828 }
00829 
00830 static FASTCALL CARD32
00831 fbFetchPixel_a2r2g2b2 (const FbBits *bits, int offset, miIndexedPtr indexed)
00832 {
00833     CARD32   pixel = ((CARD8 *) bits)[offset];
00834     CARD32   a,r,g,b;
00835 
00836     a = ((pixel & 0xc0) * 0x55) << 18;
00837     r = ((pixel & 0x30) * 0x55) << 12;
00838     g = ((pixel & 0x0c) * 0x55) << 6;
00839     b = ((pixel & 0x03) * 0x55);
00840     return a|r|g|b;
00841 }
00842 
00843 static FASTCALL CARD32
00844 fbFetchPixel_a2b2g2r2 (const FbBits *bits, int offset, miIndexedPtr indexed)
00845 {
00846     CARD32   pixel = ((CARD8 *) bits)[offset];
00847     CARD32   a,r,g,b;
00848 
00849     a = ((pixel & 0xc0) * 0x55) << 18;
00850     b = ((pixel & 0x30) * 0x55) >> 6;
00851     g = ((pixel & 0x0c) * 0x55) << 6;
00852     r = ((pixel & 0x03) * 0x55) << 16;
00853     return a|r|g|b;
00854 }
00855 
00856 static FASTCALL CARD32
00857 fbFetchPixel_c8 (const FbBits *bits, int offset, miIndexedPtr indexed)
00858 {
00859     CARD32   pixel = ((CARD8 *) bits)[offset];
00860     return indexed->rgba[pixel];
00861 }
00862 
00863 #define Fetch8(l,o)    (((CARD8 *) (l))[(o) >> 2])
00864 #if IMAGE_BYTE_ORDER == MSBFirst
00865 #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4)
00866 #else
00867 #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf)
00868 #endif
00869 
00870 static FASTCALL CARD32
00871 fbFetchPixel_a4 (const FbBits *bits, int offset, miIndexedPtr indexed)
00872 {
00873     CARD32  pixel = Fetch4(bits, offset);
00874 
00875     pixel |= pixel << 4;
00876     return pixel << 24;
00877 }
00878 
00879 static FASTCALL CARD32
00880 fbFetchPixel_r1g2b1 (const FbBits *bits, int offset, miIndexedPtr indexed)
00881 {
00882     CARD32  pixel = Fetch4(bits, offset);
00883     CARD32  r,g,b;
00884 
00885     r = ((pixel & 0x8) * 0xff) << 13;
00886     g = ((pixel & 0x6) * 0x55) << 7;
00887     b = ((pixel & 0x1) * 0xff);
00888     return 0xff000000|r|g|b;
00889 }
00890 
00891 static FASTCALL CARD32
00892 fbFetchPixel_b1g2r1 (const FbBits *bits, int offset, miIndexedPtr indexed)
00893 {
00894     CARD32  pixel = Fetch4(bits, offset);
00895     CARD32  r,g,b;
00896 
00897     b = ((pixel & 0x8) * 0xff) >> 3;
00898     g = ((pixel & 0x6) * 0x55) << 7;
00899     r = ((pixel & 0x1) * 0xff) << 16;
00900     return 0xff000000|r|g|b;
00901 }
00902 
00903 static FASTCALL CARD32
00904 fbFetchPixel_a1r1g1b1 (const FbBits *bits, int offset, miIndexedPtr indexed)
00905 {
00906     CARD32  pixel = Fetch4(bits, offset);
00907     CARD32  a,r,g,b;
00908 
00909     a = ((pixel & 0x8) * 0xff) << 21;
00910     r = ((pixel & 0x4) * 0xff) << 14;
00911     g = ((pixel & 0x2) * 0xff) << 7;
00912     b = ((pixel & 0x1) * 0xff);
00913     return a|r|g|b;
00914 }
00915 
00916 static FASTCALL CARD32
00917 fbFetchPixel_a1b1g1r1 (const FbBits *bits, int offset, miIndexedPtr indexed)
00918 {
00919     CARD32  pixel = Fetch4(bits, offset);
00920     CARD32  a,r,g,b;
00921 
00922     a = ((pixel & 0x8) * 0xff) << 21;
00923     r = ((pixel & 0x4) * 0xff) >> 3;
00924     g = ((pixel & 0x2) * 0xff) << 7;
00925     b = ((pixel & 0x1) * 0xff) << 16;
00926     return a|r|g|b;
00927 }
00928 
00929 static FASTCALL CARD32
00930 fbFetchPixel_c4 (const FbBits *bits, int offset, miIndexedPtr indexed)
00931 {
00932     CARD32  pixel = Fetch4(bits, offset);
00933 
00934     return indexed->rgba[pixel];
00935 }
00936 
00937 
00938 static FASTCALL CARD32
00939 fbFetchPixel_a1 (const FbBits *bits, int offset, miIndexedPtr indexed)
00940 {
00941     CARD32  pixel = ((CARD32 *)bits)[offset >> 5];
00942     CARD32  a;
00943 #if BITMAP_BIT_ORDER == MSBFirst
00944     a = pixel >> (0x1f - (offset & 0x1f));
00945 #else
00946     a = pixel >> (offset & 0x1f);
00947 #endif
00948     a = a & 1;
00949     a |= a << 1;
00950     a |= a << 2;
00951     a |= a << 4;
00952     return a << 24;
00953 }
00954 
00955 static FASTCALL CARD32
00956 fbFetchPixel_g1 (const FbBits *bits, int offset, miIndexedPtr indexed)
00957 {
00958     CARD32 pixel = ((CARD32 *)bits)[offset >> 5];
00959     CARD32 a;
00960 #if BITMAP_BIT_ORDER == MSBFirst
00961     a = pixel >> (0x1f - (offset & 0x1f));
00962 #else
00963     a = pixel >> (offset & 0x1f);
00964 #endif
00965     a = a & 1;
00966     return indexed->rgba[a];
00967 }
00968 
00969 static fetchPixelProc fetchPixelProcForPicture (PicturePtr pict)
00970 {
00971     switch(pict->format_code) {
00972     case PICT_a8r8g8b8: return fbFetchPixel_a8r8g8b8;
00973     case PICT_x8r8g8b8: return fbFetchPixel_x8r8g8b8;
00974     case PICT_a8b8g8r8: return fbFetchPixel_a8b8g8r8;
00975     case PICT_x8b8g8r8: return fbFetchPixel_x8b8g8r8;
00976 
00977         /* 24bpp formats */
00978     case PICT_r8g8b8: return fbFetchPixel_r8g8b8;
00979     case PICT_b8g8r8: return fbFetchPixel_b8g8r8;
00980 
00981         /* 16bpp formats */
00982     case PICT_r5g6b5: return fbFetchPixel_r5g6b5;
00983     case PICT_b5g6r5: return fbFetchPixel_b5g6r5;
00984 
00985     case PICT_a1r5g5b5: return fbFetchPixel_a1r5g5b5;
00986     case PICT_x1r5g5b5: return fbFetchPixel_x1r5g5b5;
00987     case PICT_a1b5g5r5: return fbFetchPixel_a1b5g5r5;
00988     case PICT_x1b5g5r5: return fbFetchPixel_x1b5g5r5;
00989     case PICT_a4r4g4b4: return fbFetchPixel_a4r4g4b4;
00990     case PICT_x4r4g4b4: return fbFetchPixel_x4r4g4b4;
00991     case PICT_a4b4g4r4: return fbFetchPixel_a4b4g4r4;
00992     case PICT_x4b4g4r4: return fbFetchPixel_x4b4g4r4;
00993 
00994         /* 8bpp formats */
00995     case PICT_a8: return  fbFetchPixel_a8;
00996     case PICT_r3g3b2: return fbFetchPixel_r3g3b2;
00997     case PICT_b2g3r3: return fbFetchPixel_b2g3r3;
00998     case PICT_a2r2g2b2: return fbFetchPixel_a2r2g2b2;
00999     case PICT_a2b2g2r2: return fbFetchPixel_a2b2g2r2;
01000     case PICT_c8: return  fbFetchPixel_c8;
01001     case PICT_g8: return  fbFetchPixel_c8;
01002 
01003         /* 4bpp formats */
01004     case PICT_a4: return  fbFetchPixel_a4;
01005     case PICT_r1g2b1: return fbFetchPixel_r1g2b1;
01006     case PICT_b1g2r1: return fbFetchPixel_b1g2r1;
01007     case PICT_a1r1g1b1: return fbFetchPixel_a1r1g1b1;
01008     case PICT_a1b1g1r1: return fbFetchPixel_a1b1g1r1;
01009     case PICT_c4: return  fbFetchPixel_c4;
01010     case PICT_g4: return  fbFetchPixel_c4;
01011 
01012         /* 1bpp formats */
01013     case PICT_a1: return  fbFetchPixel_a1;
01014     case PICT_g1: return  fbFetchPixel_g1;
01015     default:
01016         return NULL;
01017     }
01018 }
01019 
01020 
01021 
01022 /*
01023  * All the store functions
01024  */
01025 
01026 typedef FASTCALL void (*storeProc) (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed);
01027 
01028 #define Splita(v)    CARD32 a = ((v) >> 24), r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff
01029 #define Split(v)     CARD32 r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff
01030 
01031 static FASTCALL void
01032 fbStore_a8r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01033 {
01034     memcpy(((CARD32 *)bits) + x, values, width*sizeof(CARD32));
01035 }
01036 
01037 static FASTCALL void
01038 fbStore_x8r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01039 {
01040     int i;
01041     CARD32 *pixel = (CARD32 *)bits + x;
01042     for (i = 0; i < width; ++i)
01043         *pixel++ = values[i] & 0xffffff;
01044 }
01045 
01046 static FASTCALL void
01047 fbStore_a8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01048 {
01049     int i;
01050     CARD32 *pixel = (CARD32 *)bits + x;
01051     for (i = 0; i < width; ++i)
01052         *pixel++ = (values[i] & 0xff00ff00) | ((values[i] >> 16) & 0xff) | ((values[i] & 0xff) << 16);
01053 }
01054 
01055 static FASTCALL void
01056 fbStore_x8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01057 {
01058     int i;
01059     CARD32 *pixel = (CARD32 *)bits + x;
01060     for (i = 0; i < width; ++i)
01061         *pixel++ = (values[i] & 0x0000ff00) | ((values[i] >> 16) & 0xff) | ((values[i] & 0xff) << 16);
01062 }
01063 
01064 static FASTCALL void
01065 fbStore_r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01066 {
01067     int i;
01068     CARD8 *pixel = ((CARD8 *) bits) + x;
01069     for (i = 0; i < width; ++i) {
01070         Store24(pixel, values[i]);
01071         pixel += 3;
01072     }
01073 }
01074 
01075 static FASTCALL void
01076 fbStore_b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01077 {
01078     int i;
01079     CARD8 *pixel = ((CARD8 *) bits) + x;
01080     for (i = 0; i < width; ++i) {
01081 #if IMAGE_BYTE_ORDER == MSBFirst
01082         *pixel++ = Blue(values[i]);
01083         *pixel++ = Green(values[i]);
01084         *pixel++ = Red(values[i]);
01085 #else
01086         *pixel++ = Red(values[i]);
01087         *pixel++ = Green(values[i]);
01088         *pixel++ = Blue(values[i]);
01089 #endif
01090     }
01091 }
01092 
01093 static FASTCALL void
01094 fbStore_r5g6b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01095 {
01096     int i;
01097     CARD16 *pixel = ((CARD16 *) bits) + x;
01098     for (i = 0; i < width; ++i) {
01099         CARD32 s = values[i];
01100         *pixel++ = ((s >> 3) & 0x001f) |
01101                    ((s >> 5) & 0x07e0) |
01102                    ((s >> 8) & 0xf800);
01103     }
01104 }
01105 
01106 static FASTCALL void
01107 fbStore_b5g6r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01108 {
01109     int i;
01110     CARD16  *pixel = ((CARD16 *) bits) + x;
01111     for (i = 0; i < width; ++i) {
01112         Split(values[i]);
01113         *pixel++ = (((b << 8) & 0xf800) |
01114                     ((g << 3) & 0x07e0) |
01115                     ((r >> 3)         ));
01116     }
01117 }
01118 
01119 static FASTCALL void
01120 fbStore_a1r5g5b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01121 {
01122     int i;
01123     CARD16  *pixel = ((CARD16 *) bits) + x;
01124     for (i = 0; i < width; ++i) {
01125         Splita(values[i]);
01126         *pixel++ = (((a << 8) & 0x8000) |
01127                     ((r << 7) & 0x7c00) |
01128                     ((g << 2) & 0x03e0) |
01129                     ((b >> 3)         ));
01130     }
01131 }
01132 
01133 static FASTCALL void
01134 fbStore_x1r5g5b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01135 {
01136     int i;
01137     CARD16  *pixel = ((CARD16 *) bits) + x;
01138     for (i = 0; i < width; ++i) {
01139         Split(values[i]);
01140         *pixel++ = (((r << 7) & 0x7c00) |
01141                     ((g << 2) & 0x03e0) |
01142                     ((b >> 3)         ));
01143     }
01144 }
01145 
01146 static FASTCALL void
01147 fbStore_a1b5g5r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01148 {
01149     int i;
01150     CARD16  *pixel = ((CARD16 *) bits) + x;
01151     for (i = 0; i < width; ++i) {
01152         Splita(values[i]);
01153         *pixel++ = (((a << 8) & 0x8000) |
01154                     ((b << 7) & 0x7c00) |
01155                     ((g << 2) & 0x03e0) |
01156                     ((r >> 3)         ));
01157     }
01158 }
01159 
01160 static FASTCALL void
01161 fbStore_x1b5g5r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01162 {
01163     int i;
01164     CARD16  *pixel = ((CARD16 *) bits) + x;
01165     for (i = 0; i < width; ++i) {
01166         Split(values[i]);
01167         *pixel++ = (((b << 7) & 0x7c00) |
01168                     ((g << 2) & 0x03e0) |
01169                     ((r >> 3)         ));
01170     }
01171 }
01172 
01173 static FASTCALL void
01174 fbStore_a4r4g4b4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01175 {
01176     int i;
01177     CARD16  *pixel = ((CARD16 *) bits) + x;
01178     for (i = 0; i < width; ++i) {
01179         Splita(values[i]);
01180         *pixel++ = (((a << 8) & 0xf000) |
01181                     ((r << 4) & 0x0f00) |
01182                     ((g     ) & 0x00f0) |
01183                     ((b >> 4)         ));
01184     }
01185 }
01186 
01187 static FASTCALL void
01188 fbStore_x4r4g4b4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01189 {
01190     int i;
01191     CARD16  *pixel = ((CARD16 *) bits) + x;
01192     for (i = 0; i < width; ++i) {
01193         Split(values[i]);
01194         *pixel++ = (((r << 4) & 0x0f00) |
01195                     ((g     ) & 0x00f0) |
01196                     ((b >> 4)         ));
01197     }
01198 }
01199 
01200 static FASTCALL void
01201 fbStore_a4b4g4r4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01202 {
01203     int i;
01204     CARD16  *pixel = ((CARD16 *) bits) + x;
01205     for (i = 0; i < width; ++i) {
01206         Splita(values[i]);
01207         *pixel++ = (((a << 8) & 0xf000) |
01208                     ((b << 4) & 0x0f00) |
01209                     ((g     ) & 0x00f0) |
01210                     ((r >> 4)         ));
01211     }
01212 }
01213 
01214 static FASTCALL void
01215 fbStore_x4b4g4r4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01216 {
01217     int i;
01218     CARD16  *pixel = ((CARD16 *) bits) + x;
01219     for (i = 0; i < width; ++i) {
01220         Split(values[i]);
01221         *pixel++ = (((b << 4) & 0x0f00) |
01222                     ((g     ) & 0x00f0) |
01223                     ((r >> 4)         ));
01224     }
01225 }
01226 
01227 static FASTCALL void
01228 fbStore_a8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01229 {
01230     int i;
01231     CARD8   *pixel = ((CARD8 *) bits) + x;
01232     for (i = 0; i < width; ++i) {
01233         *pixel++ = values[i] >> 24;
01234        }
01235 }
01236 
01237 static FASTCALL void
01238 fbStore_r3g3b2 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01239 {
01240     int i;
01241     CARD8   *pixel = ((CARD8 *) bits) + x;
01242     for (i = 0; i < width; ++i) {
01243         Split(values[i]);
01244         *pixel++ = (((r     ) & 0xe0) |
01245                     ((g >> 3) & 0x1c) |
01246                     ((b >> 6)       ));
01247     }
01248 }
01249 
01250 static FASTCALL void
01251 fbStore_b2g3r3 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01252 {
01253     int i;
01254     CARD8   *pixel = ((CARD8 *) bits) + x;
01255     for (i = 0; i < width; ++i) {
01256         Split(values[i]);
01257         *pixel++ = (((b     ) & 0xe0) |
01258                     ((g >> 3) & 0x1c) |
01259                     ((r >> 6)       ));
01260     }
01261 }
01262 
01263 static FASTCALL void
01264 fbStore_a2r2g2b2 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01265 {
01266     int i;
01267     CARD8   *pixel = ((CARD8 *) bits) + x;
01268     for (i = 0; i < width; ++i) {
01269         Splita(values[i]);
01270         *pixel++ = (((a     ) & 0xc0) |
01271                     ((r >> 2) & 0x30) |
01272                     ((g >> 4) & 0x0c) |
01273                     ((b >> 6)       ));
01274     }
01275 }
01276 
01277 static FASTCALL void
01278 fbStore_c8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01279 {
01280     int i;
01281     CARD8   *pixel = ((CARD8 *) bits) + x;
01282     for (i = 0; i < width; ++i) {
01283         *pixel++ = miIndexToEnt24(indexed,values[i]);
01284     }
01285 }
01286 
01287 #define Store8(l,o,v)  (((CARD8 *) l)[(o) >> 3] = (v))
01288 #if IMAGE_BYTE_ORDER == MSBFirst
01289 #define Store4(l,o,v)  Store8(l,o,((o) & 4 ? \
01290                                (Fetch8(l,o) & 0xf0) | (v) : \
01291                                (Fetch8(l,o) & 0x0f) | ((v) << 4)))
01292 #else
01293 #define Store4(l,o,v)  Store8(l,o,((o) & 4 ? \
01294                                (Fetch8(l,o) & 0x0f) | ((v) << 4) : \
01295                                (Fetch8(l,o) & 0xf0) | (v)))
01296 #endif
01297 
01298 static FASTCALL void
01299 fbStore_a4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01300 {
01301     int i;
01302     for (i = 0; i < width; ++i) {
01303         Store4(bits, i + x, values[i]>>28);
01304     }
01305 }
01306 
01307 static FASTCALL void
01308 fbStore_r1g2b1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01309 {
01310     int i;
01311     for (i = 0; i < width; ++i) {
01312         CARD32  pixel;
01313 
01314         Split(values[i]);
01315         pixel = (((r >> 4) & 0x8) |
01316                  ((g >> 5) & 0x6) |
01317                  ((b >> 7)      ));
01318         Store4(bits, i + x, pixel);
01319     }
01320 }
01321 
01322 static FASTCALL void
01323 fbStore_b1g2r1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01324 {
01325     int i;
01326     for (i = 0; i < width; ++i) {
01327         CARD32  pixel;
01328 
01329         Split(values[i]);
01330         pixel = (((b >> 4) & 0x8) |
01331                  ((g >> 5) & 0x6) |
01332                  ((r >> 7)      ));
01333         Store4(bits, i + x, pixel);
01334     }
01335 }
01336 
01337 static FASTCALL void
01338 fbStore_a1r1g1b1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01339 {
01340     int i;
01341     for (i = 0; i < width; ++i) {
01342         CARD32  pixel;
01343         Splita(values[i]);
01344         pixel = (((a >> 4) & 0x8) |
01345                  ((r >> 5) & 0x4) |
01346                  ((g >> 6) & 0x2) |
01347                  ((b >> 7)      ));
01348         Store4(bits, i + x, pixel);
01349     }
01350 }
01351 
01352 static FASTCALL void
01353 fbStore_a1b1g1r1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01354 {
01355     int i;
01356     for (i = 0; i < width; ++i) {
01357         CARD32  pixel;
01358         Splita(values[i]);
01359         pixel = (((a >> 4) & 0x8) |
01360                  ((b >> 5) & 0x4) |
01361                  ((g >> 6) & 0x2) |
01362                  ((r >> 7)      ));
01363         Store4(bits, i + x, pixel);
01364     }
01365 }
01366 
01367 static FASTCALL void
01368 fbStore_c4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01369 {
01370     int i;
01371     for (i = 0; i < width; ++i) {
01372         CARD32  pixel;
01373 
01374         pixel = miIndexToEnt24(indexed, values[i]);
01375         Store4(bits, i + x, pixel);
01376     }
01377 }
01378 
01379 static FASTCALL void
01380 fbStore_a1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01381 {
01382     int i;
01383     for (i = 0; i < width; ++i) {
01384         CARD32  *pixel = ((CARD32 *) bits) + ((i+x) >> 5);
01385         CARD32  mask = FbStipMask((i+x) & 0x1f, 1);
01386 
01387         CARD32 v = values[i] & 0x80000000 ? mask : 0;
01388         *pixel = (*pixel & ~mask) | v;
01389     }
01390 }
01391 
01392 static FASTCALL void
01393 fbStore_g1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
01394 {
01395     int i;
01396     for (i = 0; i < width; ++i) {
01397         CARD32  *pixel = ((CARD32 *) bits) + ((i+x) >> 5);
01398         CARD32  mask = FbStipMask((i+x) & 0x1f, 1);
01399 
01400         CARD32 v = miIndexToEntY24(indexed,values[i]) ? mask : 0;
01401         *pixel = (*pixel & ~mask) | v;
01402     }
01403 }
01404 
01405 
01406 static storeProc storeProcForPicture (PicturePtr pict)
01407 {
01408     switch(pict->format_code) {
01409     case PICT_a8r8g8b8: return fbStore_a8r8g8b8;
01410     case PICT_x8r8g8b8: return fbStore_x8r8g8b8;
01411     case PICT_a8b8g8r8: return fbStore_a8b8g8r8;
01412     case PICT_x8b8g8r8: return fbStore_x8b8g8r8;
01413 
01414         /* 24bpp formats */
01415     case PICT_r8g8b8: return fbStore_r8g8b8;
01416     case PICT_b8g8r8: return fbStore_b8g8r8;
01417 
01418         /* 16bpp formats */
01419     case PICT_r5g6b5: return fbStore_r5g6b5;
01420     case PICT_b5g6r5: return fbStore_b5g6r5;
01421 
01422     case PICT_a1r5g5b5: return fbStore_a1r5g5b5;
01423     case PICT_x1r5g5b5: return fbStore_x1r5g5b5;
01424     case PICT_a1b5g5r5: return fbStore_a1b5g5r5;
01425     case PICT_x1b5g5r5: return fbStore_x1b5g5r5;
01426     case PICT_a4r4g4b4: return fbStore_a4r4g4b4;
01427     case PICT_x4r4g4b4: return fbStore_x4r4g4b4;
01428     case PICT_a4b4g4r4: return fbStore_a4b4g4r4;
01429     case PICT_x4b4g4r4: return fbStore_x4b4g4r4;
01430 
01431         /* 8bpp formats */
01432     case PICT_a8: return  fbStore_a8;
01433     case PICT_r3g3b2: return fbStore_r3g3b2;
01434     case PICT_b2g3r3: return fbStore_b2g3r3;
01435     case PICT_a2r2g2b2: return fbStore_a2r2g2b2;
01436     case PICT_c8: return  fbStore_c8;
01437     case PICT_g8: return  fbStore_c8;
01438 
01439         /* 4bpp formats */
01440     case PICT_a4: return  fbStore_a4;
01441     case PICT_r1g2b1: return fbStore_r1g2b1;
01442     case PICT_b1g2r1: return fbStore_b1g2r1;
01443     case PICT_a1r1g1b1: return fbStore_a1r1g1b1;
01444     case PICT_a1b1g1r1: return fbStore_a1b1g1r1;
01445     case PICT_c4: return  fbStore_c4;
01446     case PICT_g4: return  fbStore_c4;
01447 
01448         /* 1bpp formats */
01449     case PICT_a1: return  fbStore_a1;
01450     case PICT_g1: return  fbStore_g1;
01451     default:
01452         return NULL;
01453     }
01454 }
01455 
01456 
01457 /*
01458  * Combine src and mask
01459  */
01460 static FASTCALL void
01461 fbCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
01462 {
01463     int i;
01464     for (i = 0; i < width; ++i) {
01465         CARD32 a = mask[i] >> 24;
01466         CARD32 s = src[i];
01467         FbByteMul(s, a);
01468         src[i] = s;
01469     }
01470 }
01471 
01472 /*
01473  * All of the composing functions
01474  */
01475 
01476 static FASTCALL void
01477 fbCombineClear (CARD32 *dest, const CARD32 *src, int width)
01478 {
01479     memset(dest, 0, width*sizeof(CARD32));
01480 }
01481 
01482 static FASTCALL void
01483 fbCombineSrcU (CARD32 *dest, const CARD32 *src, int width)
01484 {
01485     memcpy(dest, src, width*sizeof(CARD32));
01486 }
01487 
01488 
01489 static FASTCALL void
01490 fbCombineOverU (CARD32 *dest, const CARD32 *src, int width)
01491 {
01492     int i;
01493     for (i = 0; i < width; ++i) {
01494         CARD32 s = src[i];
01495         CARD32 d = dest[i];
01496         CARD32 ia = Alpha(~s);
01497 
01498         FbByteMulAdd(d, ia, s);
01499         dest[i] = d;
01500     }
01501 }
01502 
01503 static FASTCALL void
01504 fbCombineOverReverseU (CARD32 *dest, const CARD32 *src, int width)
01505 {
01506     int i;
01507     for (i = 0; i < width; ++i) {
01508         CARD32 s = src[i];
01509         CARD32 d = dest[i];
01510         CARD32 ia = Alpha(~dest[i]);
01511         FbByteMulAdd(s, ia, d);
01512         dest[i] = s;
01513     }
01514 }
01515 
01516 static FASTCALL void
01517 fbCombineInU (CARD32 *dest, const CARD32 *src, int width)
01518 {
01519     int i;
01520     for (i = 0; i < width; ++i) {
01521         CARD32 s = src[i];
01522         CARD32 a = Alpha(dest[i]);
01523         FbByteMul(s, a);
01524         dest[i] = s;
01525     }
01526 }
01527 
01528 static FASTCALL void
01529 fbCombineInReverseU (CARD32 *dest, const CARD32 *src, int width)
01530 {
01531     int i;
01532     for (i = 0; i < width; ++i) {
01533         CARD32 d = dest[i];
01534         CARD32 a = Alpha(src[i]);
01535         FbByteMul(d, a);
01536         dest[i] = d;
01537     }
01538 }
01539 
01540 static FASTCALL void
01541 fbCombineOutU (CARD32 *dest, const CARD32 *src, int width)
01542 {
01543     int i;
01544     for (i = 0; i < width; ++i) {
01545         CARD32 s = src[i];
01546         CARD32 a = Alpha(~dest[i]);
01547         FbByteMul(s, a);
01548         dest[i] = s;
01549     }
01550 }
01551 
01552 static FASTCALL void
01553 fbCombineOutReverseU (CARD32 *dest, const CARD32 *src, int width)
01554 {
01555     int i;
01556     for (i = 0; i < width; ++i) {
01557         CARD32 d = dest[i];
01558         CARD32 a = Alpha(~src[i]);
01559         FbByteMul(d, a);
01560         dest[i] = d;
01561     }
01562 }
01563 
01564 static FASTCALL void
01565 fbCombineAtopU (CARD32 *dest, const CARD32 *src, int width)
01566 {
01567     int i;
01568     for (i = 0; i < width; ++i) {
01569         CARD32 s = src[i];
01570         CARD32 d = dest[i];
01571         CARD32 dest_a = Alpha(d);
01572         CARD32 src_ia = Alpha(~s);
01573 
01574         FbByteAddMul(s, dest_a, d, src_ia);
01575         dest[i] = s;
01576     }
01577 }
01578 
01579 static FASTCALL void
01580 fbCombineAtopReverseU (CARD32 *dest, const CARD32 *src, int width)
01581 {
01582     int i;
01583     for (i = 0; i < width; ++i) {
01584         CARD32 s = src[i];
01585         CARD32 d = dest[i];
01586         CARD32 src_a = Alpha(s);
01587         CARD32 dest_ia = Alpha(~d);
01588 
01589         FbByteAddMul(s, dest_ia, d, src_a);
01590         dest[i] = s;
01591     }
01592 }
01593 
01594 static FASTCALL void
01595 fbCombineXorU (CARD32 *dest, const CARD32 *src, int width)
01596 {
01597     int i;
01598     for (i = 0; i < width; ++i) {
01599         CARD32 s = src[i];
01600         CARD32 d = dest[i];
01601         CARD32 src_ia = Alpha(~s);
01602         CARD32 dest_ia = Alpha(~d);
01603 
01604         FbByteAddMul(s, dest_ia, d, src_ia);
01605         dest[i] = s;
01606     }
01607 }
01608 
01609 static FASTCALL void
01610 fbCombineAddU (CARD32 *dest, const CARD32 *src, int width)
01611 {
01612     int i;
01613     for (i = 0; i < width; ++i) {
01614         CARD32 s = src[i];
01615         CARD32 d = dest[i];
01616         FbByteAdd(d, s);
01617         dest[i] = d;
01618     }
01619 }
01620 
01621 static FASTCALL void
01622 fbCombineSaturateU (CARD32 *dest, const CARD32 *src, int width)
01623 {
01624     int i;
01625     for (i = 0; i < width; ++i) {
01626         CARD32  s = src[i];
01627         CARD32 d = dest[i];
01628         CARD16  sa, da;
01629 
01630         sa = s >> 24;
01631         da = ~d >> 24;
01632         if (sa > da)
01633         {
01634             sa = FbIntDiv(da, sa);
01635             FbByteMul(s, sa);
01636         }
01637         FbByteAdd(d, s);
01638         dest[i] = d;
01639     }
01640 }
01641 
01642 /*
01643  * All of the disjoint composing functions
01644 
01645  The four entries in the first column indicate what source contributions
01646  come from each of the four areas of the picture -- areas covered by neither
01647  A nor B, areas covered only by A, areas covered only by B and finally
01648  areas covered by both A and B.
01649 
01650               Disjoint                    Conjoint
01651               Fa            Fb            Fa            Fb
01652 (0,0,0,0)     0             0             0             0
01653 (0,A,0,A)     1             0             1             0
01654 (0,0,B,B)     0             1             0             1
01655 (0,A,B,A)     1             min((1-a)/b,1)       1             max(1-a/b,0)
01656 (0,A,B,B)     min((1-b)/a,1)       1             max(1-b/a,0)  1
01657 (0,0,0,A)     max(1-(1-b)/a,0) 0          min(1,b/a)    0
01658 (0,0,0,B)     0             max(1-(1-a)/b,0) 0          min(a/b,1)
01659 (0,A,0,0)     min(1,(1-b)/a)       0             max(1-b/a,0)  0
01660 (0,0,B,0)     0             min(1,(1-a)/b)       0             max(1-a/b,0)
01661 (0,0,B,A)     max(1-(1-b)/a,0) min(1,(1-a)/b)     min(1,b/a)   max(1-a/b,0)
01662 (0,A,0,B)     min(1,(1-b)/a)       max(1-(1-a)/b,0) max(1-b/a,0)      min(1,a/b)
01663 (0,A,B,0)     min(1,(1-b)/a)       min(1,(1-a)/b)       max(1-b/a,0)  max(1-a/b,0)
01664 
01665  */
01666 
01667 #define CombineAOut 1
01668 #define CombineAIn  2
01669 #define CombineBOut 4
01670 #define CombineBIn  8
01671 
01672 #define CombineClear 0
01673 #define CombineA     (CombineAOut|CombineAIn)
01674 #define CombineB     (CombineBOut|CombineBIn)
01675 #define CombineAOver (CombineAOut|CombineBOut|CombineAIn)
01676 #define CombineBOver (CombineAOut|CombineBOut|CombineBIn)
01677 #define CombineAAtop (CombineBOut|CombineAIn)
01678 #define CombineBAtop (CombineAOut|CombineBIn)
01679 #define CombineXor   (CombineAOut|CombineBOut)
01680 
01681 /* portion covered by a but not b */
01682 static INLINE CARD8
01683 fbCombineDisjointOutPart (CARD8 a, CARD8 b)
01684 {
01685     /* min (1, (1-b) / a) */
01686 
01687     b = ~b;              /* 1 - b */
01688     if (b >= a)                 /* 1 - b >= a -> (1-b)/a >= 1 */
01689        return 0xff;      /* 1 */
01690     return FbIntDiv(b,a);   /* (1-b) / a */
01691 }
01692 
01693 /* portion covered by both a and b */
01694 static INLINE CARD8
01695 fbCombineDisjointInPart (CARD8 a, CARD8 b)
01696 {
01697     /* max (1-(1-b)/a,0) */
01698     /*  = - min ((1-b)/a - 1, 0) */
01699     /*  = 1 - min (1, (1-b)/a) */
01700 
01701     b = ~b;              /* 1 - b */
01702     if (b >= a)                 /* 1 - b >= a -> (1-b)/a >= 1 */
01703        return 0;         /* 1 - 1 */
01704     return ~FbIntDiv(b,a);  /* 1 - (1-b) / a */
01705 }
01706 
01707 static FASTCALL void
01708 fbCombineDisjointGeneralU (CARD32 *dest, const CARD32 *src, int width, CARD8 combine)
01709 {
01710     int i;
01711     for (i = 0; i < width; ++i) {
01712         CARD32 s = src[i];
01713         CARD32 d = dest[i];
01714         CARD32 m,n,o,p;
01715         CARD16 Fa, Fb, t, u, v;
01716         CARD8 sa = s >> 24;
01717         CARD8 da = d >> 24;
01718 
01719         switch (combine & CombineA) {
01720         default:
01721             Fa = 0;
01722             break;
01723         case CombineAOut:
01724             Fa = fbCombineDisjointOutPart (sa, da);
01725             break;
01726         case CombineAIn:
01727             Fa = fbCombineDisjointInPart (sa, da);
01728             break;
01729         case CombineA:
01730             Fa = 0xff;
01731             break;
01732         }
01733 
01734         switch (combine & CombineB) {
01735         default:
01736             Fb = 0;
01737             break;
01738         case CombineBOut:
01739             Fb = fbCombineDisjointOutPart (da, sa);
01740             break;
01741         case CombineBIn:
01742             Fb = fbCombineDisjointInPart (da, sa);
01743             break;
01744         case CombineB:
01745             Fb = 0xff;
01746             break;
01747         }
01748         m = FbGen (s,d,0,Fa,Fb,t, u, v);
01749         n = FbGen (s,d,8,Fa,Fb,t, u, v);
01750         o = FbGen (s,d,16,Fa,Fb,t, u, v);
01751         p = FbGen (s,d,24,Fa,Fb,t, u, v);
01752         s = m|n|o|p;
01753         dest[i] = s;
01754     }
01755 }
01756 
01757 static FASTCALL void
01758 fbCombineDisjointOverU (CARD32 *dest, const CARD32 *src, int width)
01759 {
01760     int i;
01761     for (i = 0; i < width; ++i) {
01762         CARD32  s = src[i];
01763         CARD16  a = s >> 24;
01764 
01765         if (a != 0x00)
01766         {
01767             if (a != 0xff)
01768             {
01769                 CARD32 d = dest[i];
01770                 a = fbCombineDisjointOutPart (d >> 24, a);
01771                 FbByteMulAdd(d, a, s);
01772                 s = d;
01773             }
01774             dest[i] = s;
01775         }
01776     }
01777 }
01778 
01779 static FASTCALL void
01780 fbCombineDisjointInU (CARD32 *dest, const CARD32 *src, int width)
01781 {
01782     fbCombineDisjointGeneralU (dest, src, width, CombineAIn);
01783 }
01784 
01785 static FASTCALL void
01786 fbCombineDisjointInReverseU (CARD32 *dest, const CARD32 *src, int width)
01787 {
01788     fbCombineDisjointGeneralU (dest, src, width, CombineBIn);
01789 }
01790 
01791 static FASTCALL void
01792 fbCombineDisjointOutU (CARD32 *dest, const CARD32 *src, int width)
01793 {
01794     fbCombineDisjointGeneralU (dest, src, width, CombineAOut);
01795 }
01796 
01797 static FASTCALL void
01798 fbCombineDisjointOutReverseU (CARD32 *dest, const CARD32 *src, int width)
01799 {
01800     fbCombineDisjointGeneralU (dest, src, width, CombineBOut);
01801 }
01802 
01803 static FASTCALL void
01804 fbCombineDisjointAtopU (CARD32 *dest, const CARD32 *src, int width)
01805 {
01806     fbCombineDisjointGeneralU (dest, src, width, CombineAAtop);
01807 }
01808 
01809 static FASTCALL void
01810 fbCombineDisjointAtopReverseU (CARD32 *dest, const CARD32 *src, int width)
01811 {
01812     fbCombineDisjointGeneralU (dest, src, width, CombineBAtop);
01813 }
01814 
01815 static FASTCALL void
01816 fbCombineDisjointXorU (CARD32 *dest, const CARD32 *src, int width)
01817 {
01818     fbCombineDisjointGeneralU (dest, src, width, CombineXor);
01819 }
01820 
01821 /* portion covered by a but not b */
01822 static INLINE CARD8
01823 fbCombineConjointOutPart (CARD8 a, CARD8 b)
01824 {
01825     /* max (1-b/a,0) */
01826     /* = 1-min(b/a,1) */
01827 
01828     /* min (1, (1-b) / a) */
01829 
01830     if (b >= a)                 /* b >= a -> b/a >= 1 */
01831        return 0x00;      /* 0 */
01832     return ~FbIntDiv(b,a);   /* 1 - b/a */
01833 }
01834 
01835 /* portion covered by both a and b */
01836 static INLINE CARD8
01837 fbCombineConjointInPart (CARD8 a, CARD8 b)
01838 {
01839     /* min (1,b/a) */
01840 
01841     if (b >= a)                 /* b >= a -> b/a >= 1 */
01842        return 0xff;      /* 1 */
01843     return FbIntDiv(b,a);   /* b/a */
01844 }
01845 
01846 static FASTCALL void
01847 fbCombineConjointGeneralU (CARD32 *dest, const CARD32 *src, int width, CARD8 combine)
01848 {
01849     int i;
01850     for (i = 0; i < width; ++i) {
01851         CARD32  s = src[i];
01852         CARD32 d = dest[i];
01853         CARD32  m,n,o,p;
01854         CARD16  Fa, Fb, t, u, v;
01855         CARD8 sa = s >> 24;
01856         CARD8 da = d >> 24;
01857 
01858         switch (combine & CombineA) {
01859         default:
01860             Fa = 0;
01861             break;
01862         case CombineAOut:
01863             Fa = fbCombineConjointOutPart (sa, da);
01864             break;
01865         case CombineAIn:
01866             Fa = fbCombineConjointInPart (sa, da);
01867             break;
01868         case CombineA:
01869             Fa = 0xff;
01870             break;
01871         }
01872 
01873         switch (combine & CombineB) {
01874         default:
01875             Fb = 0;
01876             break;
01877         case CombineBOut:
01878             Fb = fbCombineConjointOutPart (da, sa);
01879             break;
01880         case CombineBIn:
01881             Fb = fbCombineConjointInPart (da, sa);
01882             break;
01883         case CombineB:
01884             Fb = 0xff;
01885             break;
01886         }
01887         m = FbGen (s,d,0,Fa,Fb,t, u, v);
01888         n = FbGen (s,d,8,Fa,Fb,t, u, v);
01889         o = FbGen (s,d,16,Fa,Fb,t, u, v);
01890         p = FbGen (s,d,24,Fa,Fb,t, u, v);
01891         s = m|n|o|p;
01892         dest[i] = s;
01893     }
01894 }
01895 
01896 static FASTCALL void
01897 fbCombineConjointOverU (CARD32 *dest, const CARD32 *src, int width)
01898 {
01899     fbCombineConjointGeneralU (dest, src, width, CombineAOver);
01900 }
01901 
01902 
01903 static FASTCALL void
01904 fbCombineConjointOverReverseU (CARD32 *dest, const CARD32 *src, int width)
01905 {
01906     fbCombineConjointGeneralU (dest, src, width, CombineBOver);
01907 }
01908 
01909 
01910 static FASTCALL void
01911 fbCombineConjointInU (CARD32 *dest, const CARD32 *src, int width)
01912 {
01913     fbCombineConjointGeneralU (dest, src, width, CombineAIn);
01914 }
01915 
01916 
01917 static FASTCALL void
01918 fbCombineConjointInReverseU (CARD32 *dest, const CARD32 *src, int width)
01919 {
01920     fbCombineConjointGeneralU (dest, src, width, CombineBIn);
01921 }
01922 
01923 static FASTCALL void
01924 fbCombineConjointOutU (CARD32 *dest, const CARD32 *src, int width)
01925 {
01926     fbCombineConjointGeneralU (dest, src, width, CombineAOut);
01927 }
01928 
01929 static FASTCALL void
01930 fbCombineConjointOutReverseU (CARD32 *dest, const CARD32 *src, int width)
01931 {
01932     fbCombineConjointGeneralU (dest, src, width, CombineBOut);
01933 }
01934 
01935 static FASTCALL void
01936 fbCombineConjointAtopU (CARD32 *dest, const CARD32 *src, int width)
01937 {
01938     fbCombineConjointGeneralU (dest, src, width, CombineAAtop);
01939 }
01940 
01941 static FASTCALL void
01942 fbCombineConjointAtopReverseU (CARD32 *dest, const CARD32 *src, int width)
01943 {
01944     fbCombineConjointGeneralU (dest, src, width, CombineBAtop);
01945 }
01946 
01947 static FASTCALL void
01948 fbCombineConjointXorU (CARD32 *dest, const CARD32 *src, int width)
01949 {
01950     fbCombineConjointGeneralU (dest, src, width, CombineXor);
01951 }
01952 
01953 static CombineFuncU fbCombineFuncU[] = {
01954     fbCombineClear,
01955     fbCombineSrcU,
01956     NULL, /* CombineDst */
01957     fbCombineOverU,
01958     fbCombineOverReverseU,
01959     fbCombineInU,
01960     fbCombineInReverseU,
01961     fbCombineOutU,
01962     fbCombineOutReverseU,
01963     fbCombineAtopU,
01964     fbCombineAtopReverseU,
01965     fbCombineXorU,
01966     fbCombineAddU,
01967     fbCombineSaturateU,
01968     NULL,
01969     NULL,
01970     fbCombineClear,
01971     fbCombineSrcU,
01972     NULL, /* CombineDst */
01973     fbCombineDisjointOverU,
01974     fbCombineSaturateU, /* DisjointOverReverse */
01975     fbCombineDisjointInU,
01976     fbCombineDisjointInReverseU,
01977     fbCombineDisjointOutU,
01978     fbCombineDisjointOutReverseU,
01979     fbCombineDisjointAtopU,
01980     fbCombineDisjointAtopReverseU,
01981     fbCombineDisjointXorU,
01982     NULL,
01983     NULL,
01984     NULL,
01985     NULL,
01986     fbCombineClear,
01987     fbCombineSrcU,
01988     NULL, /* CombineDst */
01989     fbCombineConjointOverU,
01990     fbCombineConjointOverReverseU,
01991     fbCombineConjointInU,
01992     fbCombineConjointInReverseU,
01993     fbCombineConjointOutU,
01994     fbCombineConjointOutReverseU,
01995     fbCombineConjointAtopU,
01996     fbCombineConjointAtopReverseU,
01997     fbCombineConjointXorU,
01998 };
01999 
02000 static FASTCALL void
02001 fbCombineMaskC (CARD32 *src, CARD32 *mask, int width)
02002 {
02003     int i;
02004     for (i = 0; i < width; ++i) {
02005         CARD32 a = mask[i];
02006 
02007         CARD32       x;
02008         CARD16       xa;
02009 
02010         if (!a)
02011         {
02012             src[i] = 0;
02013             continue;
02014         }
02015 
02016         x = src[i];
02017         if (a == 0xffffffff)
02018         {
02019             x = x >> 24;
02020             x |= x << 8;
02021             x |= x << 16;
02022             mask[i] = x;
02023             continue;
02024         }
02025 
02026         xa = x >> 24;
02027         FbByteMulC(x, a);
02028         src[i] = x;
02029         FbByteMul(a, xa);
02030         mask[i] = a;
02031     }
02032 }
02033 
02034 static FASTCALL void
02035 fbCombineMaskValueC (CARD32 *src, const CARD32 *mask, int width)
02036 {
02037     int i;
02038     for (i = 0; i < width; ++i) {
02039         CARD32 a = mask[i];
02040         CARD32       x;
02041 
02042         if (!a)
02043         {
02044             src[i] = 0;
02045             continue;
02046         }
02047 
02048         if (a == 0xffffffff)
02049             continue;
02050 
02051         x = src[i];
02052         FbByteMulC(x, a);
02053         src[i] = x;
02054     }
02055 }
02056 
02057 
02058 static FASTCALL void
02059 fbCombineMaskAlphaC (const CARD32 *src, CARD32 *mask, int width)
02060 {
02061     int i;
02062     for (i = 0; i < width; ++i) {
02063         CARD32 a = mask[i];
02064         CARD32       x;
02065 
02066         if (!a)
02067             continue;
02068 
02069         x = src[i] >> 24;
02070         if (x == 0xff)
02071             continue;
02072         if (a == 0xffffffff)
02073         {
02074             x = x >> 24;
02075             x |= x << 8;
02076             x |= x << 16;
02077             mask[i] = x;
02078             continue;
02079         }
02080 
02081         FbByteMul(a, x);
02082         mask[i] = a;
02083     }
02084 }
02085 
02086 static FASTCALL void
02087 fbCombineClearC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02088 {
02089     memset(dest, 0, width*sizeof(CARD32));
02090 }
02091 
02092 static FASTCALL void
02093 fbCombineSrcC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02094 {
02095     fbCombineMaskValueC(src, mask, width);
02096     memcpy(dest, src, width*sizeof(CARD32));
02097 }
02098 
02099 static FASTCALL void
02100 fbCombineOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02101 {
02102     int i;
02103     fbCombineMaskC(src, mask, width);
02104     for (i = 0; i < width; ++i) {
02105         CARD32  s = src[i];
02106         CARD32  a = ~mask[i];
02107 
02108         if (a != 0xffffffff)
02109         {
02110             if (a)
02111             {
02112                 CARD32 d = dest[i];
02113                 FbByteMulAddC(d, a, s);
02114                 s = d;
02115             }
02116             dest[i] = s;
02117         }
02118     }
02119 }
02120 
02121 static FASTCALL void
02122 fbCombineOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02123 {
02124     int i;
02125     fbCombineMaskValueC(src, mask, width);
02126     for (i = 0; i < width; ++i) {
02127         CARD32 d = dest[i];
02128         CARD32 a = ~d >> 24;
02129 
02130         if (a)
02131         {
02132             CARD32 s = src[i];
02133             if (a != 0xff)
02134             {
02135                 FbByteMulAdd(s, a, d);
02136             }
02137             dest[i] = s;
02138         }
02139     }
02140 }
02141 
02142 static FASTCALL void
02143 fbCombineInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02144 {
02145     int i;
02146     fbCombineMaskValueC(src, mask, width);
02147     for (i = 0; i < width; ++i) {
02148         CARD32 d = dest[i];
02149         CARD16 a = d >> 24;
02150         CARD32 s = 0;
02151         if (a)
02152         {
02153             s = src[i];
02154             if (a != 0xff)
02155             {
02156                 FbByteMul(s, a);
02157             }
02158         }
02159         dest[i] = s;
02160     }
02161 }
02162 
02163 static FASTCALL void
02164 fbCombineInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02165 {
02166     int i;
02167     fbCombineMaskAlphaC(src, mask, width);
02168     for (i = 0; i < width; ++i) {
02169         CARD32 a = mask[i];
02170 
02171         if (a != 0xffffffff)
02172         {
02173             CARD32 d = 0;
02174             if (a)
02175             {
02176                 d = dest[i];
02177                 FbByteMulC(d, a);
02178             }
02179             dest[i] = d;
02180         }
02181     }
02182 }
02183 
02184 static FASTCALL void
02185 fbCombineOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02186 {
02187     int i;
02188     fbCombineMaskValueC(src, mask, width);
02189     for (i = 0; i < width; ++i) {
02190         CARD32 d = dest[i];
02191         CARD16 a = ~d >> 24;
02192         CARD32 s = 0;
02193         if (a)
02194         {
02195             s = src[i];
02196             if (a != 0xff)
02197             {
02198                 FbByteMul(s, a);
02199             }
02200         }
02201         dest[i] = s;
02202     }
02203 }
02204 
02205 static FASTCALL void
02206 fbCombineOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02207 {
02208     int i;
02209     fbCombineMaskAlphaC(src, mask, width);
02210     for (i = 0; i < width; ++i) {
02211         CARD32 a = ~mask[i];
02212 
02213         if (a != 0xffffffff)
02214         {
02215             CARD32 d = 0;
02216             if (a)
02217             {
02218                 d = dest[i];
02219                 FbByteMulC(d, a);
02220             }
02221             dest[i] = d;
02222         }
02223     }
02224 }
02225 
02226 static FASTCALL void
02227 fbCombineAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02228 {
02229     int i;
02230     fbCombineMaskC(src, mask, width);
02231     for (i = 0; i < width; ++i) {
02232         CARD32 d = dest[i];
02233         CARD32 s = src[i];
02234         CARD32 ad = ~mask[i];
02235         CARD16 as = d >> 24;
02236         FbByteAddMulC(d, ad, s, as);
02237         dest[i] = d;
02238     }
02239 }
02240 
02241 static FASTCALL void
02242 fbCombineAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02243 {
02244     int i;
02245     fbCombineMaskC(src, mask, width);
02246     for (i = 0; i < width; ++i) {
02247 
02248         CARD32 d = dest[i];
02249         CARD32 s = src[i];
02250         CARD32 ad = mask[i];
02251         CARD16 as = ~d >> 24;
02252         FbByteAddMulC(d, ad, s, as);
02253         dest[i] = d;
02254     }
02255 }
02256 
02257 static FASTCALL void
02258 fbCombineXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02259 {
02260     int i;
02261     fbCombineMaskC(src, mask, width);
02262     for (i = 0; i < width; ++i) {
02263         CARD32 d = dest[i];
02264         CARD32 s = src[i];
02265         CARD32 ad = ~mask[i];
02266         CARD16 as = ~d >> 24;
02267         FbByteAddMulC(d, ad, s, as);
02268         dest[i] = d;
02269     }
02270 }
02271 
02272 static FASTCALL void
02273 fbCombineAddC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02274 {
02275     int i;
02276     fbCombineMaskValueC(src, mask, width);
02277     for (i = 0; i < width; ++i) {
02278         CARD32 s = src[i];
02279         CARD32 d = dest[i];
02280         FbByteAdd(d, s);
02281         dest[i] = d;
02282     }
02283 }
02284 
02285 static FASTCALL void
02286 fbCombineSaturateC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02287 {
02288     int i;
02289     fbCombineMaskC(src, mask, width);
02290     for (i = 0; i < width; ++i) {
02291         CARD32  s, d;
02292         CARD16  sa, sr, sg, sb, da;
02293         CARD16  t, u, v;
02294         CARD32  m,n,o,p;
02295 
02296         d = dest[i];
02297         s = src[i];
02298         sa = (mask[i] >> 24);
02299         sr = (mask[i] >> 16) & 0xff;
02300         sg = (mask[i] >>  8) & 0xff;
02301         sb = (mask[i]      ) & 0xff;
02302         da = ~d >> 24;
02303 
02304         if (sb <= da)
02305             m = FbAdd(s,d,0,t);
02306         else
02307             m = FbGen (s, d, 0, (da << 8) / sb, 0xff, t, u, v);
02308 
02309         if (sg <= da)
02310             n = FbAdd(s,d,8,t);
02311         else
02312             n = FbGen (s, d, 8, (da << 8) / sg, 0xff, t, u, v);
02313 
02314         if (sr <= da)
02315             o = FbAdd(s,d,16,t);
02316         else
02317             o = FbGen (s, d, 16, (da << 8) / sr, 0xff, t, u, v);
02318 
02319         if (sa <= da)
02320             p = FbAdd(s,d,24,t);
02321         else
02322             p = FbGen (s, d, 24, (da << 8) / sa, 0xff, t, u, v);
02323 
02324         dest[i] = m|n|o|p;
02325     }
02326 }
02327 
02328 static FASTCALL void
02329 fbCombineDisjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine)
02330 {
02331     int i;
02332     fbCombineMaskC(src, mask, width);
02333     for (i = 0; i < width; ++i) {
02334         CARD32  s, d;
02335         CARD32  m,n,o,p;
02336         CARD32  Fa, Fb;
02337         CARD16  t, u, v;
02338         CARD32  sa;
02339         CARD8   da;
02340 
02341         s = src[i];
02342         sa = mask[i];
02343         d = dest[i];
02344         da = d >> 24;
02345 
02346         switch (combine & CombineA) {
02347         default:
02348             Fa = 0;
02349             break;
02350         case CombineAOut:
02351             m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da);
02352             n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8;
02353             o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16;
02354             p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24;
02355             Fa = m|n|o|p;
02356             break;
02357         case CombineAIn:
02358             m = fbCombineDisjointInPart ((CARD8) (sa >> 0), da);
02359             n = fbCombineDisjointInPart ((CARD8) (sa >> 8), da) << 8;
02360             o = fbCombineDisjointInPart ((CARD8) (sa >> 16), da) << 16;
02361             p = fbCombineDisjointInPart ((CARD8) (sa >> 24), da) << 24;
02362             Fa = m|n|o|p;
02363             break;
02364         case CombineA:
02365             Fa = 0xffffffff;
02366             break;
02367         }
02368 
02369         switch (combine & CombineB) {
02370         default:
02371             Fb = 0;
02372             break;
02373         case CombineBOut:
02374             m = fbCombineDisjointOutPart (da, (CARD8) (sa >> 0));
02375             n = fbCombineDisjointOutPart (da, (CARD8) (sa >> 8)) << 8;
02376             o = fbCombineDisjointOutPart (da, (CARD8) (sa >> 16)) << 16;
02377             p = fbCombineDisjointOutPart (da, (CARD8) (sa >> 24)) << 24;
02378             Fb = m|n|o|p;
02379             break;
02380         case CombineBIn:
02381             m = fbCombineDisjointInPart (da, (CARD8) (sa >> 0));
02382             n = fbCombineDisjointInPart (da, (CARD8) (sa >> 8)) << 8;
02383             o = fbCombineDisjointInPart (da, (CARD8) (sa >> 16)) << 16;
02384             p = fbCombineDisjointInPart (da, (CARD8) (sa >> 24)) << 24;
02385             Fb = m|n|o|p;
02386             break;
02387         case CombineB:
02388             Fb = 0xffffffff;
02389             break;
02390         }
02391         m = FbGen (s,d,0,FbGet8(Fa,0),FbGet8(Fb,0),t, u, v);
02392         n = FbGen (s,d,8,FbGet8(Fa,8),FbGet8(Fb,8),t, u, v);
02393         o = FbGen (s,d,16,FbGet8(Fa,16),FbGet8(Fb,16),t, u, v);
02394         p = FbGen (s,d,24,FbGet8(Fa,24),FbGet8(Fb,24),t, u, v);
02395         s = m|n|o|p;
02396         dest[i] = s;
02397     }
02398 }
02399 
02400 static FASTCALL void
02401 fbCombineDisjointOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02402 {
02403     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAOver);
02404 }
02405 
02406 static FASTCALL void
02407 fbCombineDisjointInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02408 {
02409     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAIn);
02410 }
02411 
02412 static FASTCALL void
02413 fbCombineDisjointInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02414 {
02415     fbCombineDisjointGeneralC (dest, src, mask, width, CombineBIn);
02416 }
02417 
02418 static FASTCALL void
02419 fbCombineDisjointOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02420 {
02421     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAOut);
02422 }
02423 
02424 static FASTCALL void
02425 fbCombineDisjointOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02426 {
02427     fbCombineDisjointGeneralC (dest, src, mask, width, CombineBOut);
02428 }
02429 
02430 static FASTCALL void
02431 fbCombineDisjointAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02432 {
02433     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAAtop);
02434 }
02435 
02436 static FASTCALL void
02437 fbCombineDisjointAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02438 {
02439     fbCombineDisjointGeneralC (dest, src, mask, width, CombineBAtop);
02440 }
02441 
02442 static FASTCALL void
02443 fbCombineDisjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02444 {
02445     fbCombineDisjointGeneralC (dest, src, mask, width, CombineXor);
02446 }
02447 
02448 static FASTCALL void
02449 fbCombineConjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine)
02450 {
02451     int i;
02452     fbCombineMaskC(src, mask, width);
02453     for (i = 0; i < width; ++i) {
02454         CARD32  s, d;
02455         CARD32  m,n,o,p;
02456         CARD32  Fa, Fb;
02457         CARD16  t, u, v;
02458         CARD32  sa;
02459         CARD8   da;
02460 
02461         s = src[i];
02462         sa = mask[i];
02463         d = dest[i];
02464         da = d >> 24;
02465 
02466         switch (combine & CombineA) {
02467         default:
02468             Fa = 0;
02469             break;
02470         case CombineAOut:
02471             m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da);
02472             n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8;
02473             o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16;
02474             p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24;
02475             Fa = m|n|o|p;
02476             break;
02477         case CombineAIn:
02478             m = fbCombineConjointInPart ((CARD8) (sa >> 0), da);
02479             n = fbCombineConjointInPart ((CARD8) (sa >> 8), da) << 8;
02480             o = fbCombineConjointInPart ((CARD8) (sa >> 16), da) << 16;
02481             p = fbCombineConjointInPart ((CARD8) (sa >> 24), da) << 24;
02482             Fa = m|n|o|p;
02483             break;
02484         case CombineA:
02485             Fa = 0xffffffff;
02486             break;
02487         }
02488 
02489         switch (combine & CombineB) {
02490         default:
02491             Fb = 0;
02492             break;
02493         case CombineBOut:
02494             m = fbCombineConjointOutPart (da, (CARD8) (sa >> 0));
02495             n = fbCombineConjointOutPart (da, (CARD8) (sa >> 8)) << 8;
02496             o = fbCombineConjointOutPart (da, (CARD8) (sa >> 16)) << 16;
02497             p = fbCombineConjointOutPart (da, (CARD8) (sa >> 24)) << 24;
02498             Fb = m|n|o|p;
02499             break;
02500         case CombineBIn:
02501             m = fbCombineConjointInPart (da, (CARD8) (sa >> 0));
02502             n = fbCombineConjointInPart (da, (CARD8) (sa >> 8)) << 8;
02503             o = fbCombineConjointInPart (da, (CARD8) (sa >> 16)) << 16;
02504             p = fbCombineConjointInPart (da, (CARD8) (sa >> 24)) << 24;
02505             Fb = m|n|o|p;
02506             break;
02507         case CombineB:
02508             Fb = 0xffffffff;
02509             break;
02510         }
02511         m = FbGen (s,d,0,FbGet8(Fa,0),FbGet8(Fb,0),t, u, v);
02512         n = FbGen (s,d,8,FbGet8(Fa,8),FbGet8(Fb,8),t, u, v);
02513         o = FbGen (s,d,16,FbGet8(Fa,16),FbGet8(Fb,16),t, u, v);
02514         p = FbGen (s,d,24,FbGet8(Fa,24),FbGet8(Fb,24),t, u, v);
02515         s = m|n|o|p;
02516         dest[i] = s;
02517     }
02518 }
02519 
02520 static FASTCALL void
02521 fbCombineConjointOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02522 {
02523     fbCombineConjointGeneralC (dest, src, mask, width, CombineAOver);
02524 }
02525 
02526 static FASTCALL void
02527 fbCombineConjointOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02528 {
02529     fbCombineConjointGeneralC (dest, src, mask, width, CombineBOver);
02530 }
02531 
02532 static FASTCALL void
02533 fbCombineConjointInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02534 {
02535     fbCombineConjointGeneralC (dest, src, mask, width, CombineAIn);
02536 }
02537 
02538 static FASTCALL void
02539 fbCombineConjointInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02540 {
02541     fbCombineConjointGeneralC (dest, src, mask, width, CombineBIn);
02542 }
02543 
02544 static FASTCALL void
02545 fbCombineConjointOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02546 {
02547     fbCombineConjointGeneralC (dest, src, mask, width, CombineAOut);
02548 }
02549 
02550 static FASTCALL void
02551 fbCombineConjointOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02552 {
02553     fbCombineConjointGeneralC (dest, src, mask, width, CombineBOut);
02554 }
02555 
02556 static FASTCALL void
02557 fbCombineConjointAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02558 {
02559     fbCombineConjointGeneralC (dest, src, mask, width, CombineAAtop);
02560 }
02561 
02562 static FASTCALL void
02563 fbCombineConjointAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02564 {
02565     fbCombineConjointGeneralC (dest, src, mask, width, CombineBAtop);
02566 }
02567 
02568 static FASTCALL void
02569 fbCombineConjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
02570 {
02571     fbCombineConjointGeneralC (dest, src, mask, width, CombineXor);
02572 }
02573 
02574 static CombineFuncC fbCombineFuncC[] = {
02575     fbCombineClearC,
02576     fbCombineSrcC,
02577     NULL, /* Dest */
02578     fbCombineOverC,
02579     fbCombineOverReverseC,
02580     fbCombineInC,
02581     fbCombineInReverseC,
02582     fbCombineOutC,
02583     fbCombineOutReverseC,
02584     fbCombineAtopC,
02585     fbCombineAtopReverseC,
02586     fbCombineXorC,
02587     fbCombineAddC,
02588     fbCombineSaturateC,
02589     NULL,
02590     NULL,
02591     fbCombineClearC,     /* 0x10 */
02592     fbCombineSrcC,
02593     NULL, /* Dest */
02594     fbCombineDisjointOverC,
02595     fbCombineSaturateC, /* DisjointOverReverse */
02596     fbCombineDisjointInC,
02597     fbCombineDisjointInReverseC,
02598     fbCombineDisjointOutC,
02599     fbCombineDisjointOutReverseC,
02600     fbCombineDisjointAtopC,
02601     fbCombineDisjointAtopReverseC,
02602     fbCombineDisjointXorC,  /* 0x1b */
02603     NULL,
02604     NULL,
02605     NULL,
02606     NULL,
02607     fbCombineClearC,
02608     fbCombineSrcC,
02609     NULL, /* Dest */
02610     fbCombineConjointOverC,
02611     fbCombineConjointOverReverseC,
02612     fbCombineConjointInC,
02613     fbCombineConjointInReverseC,
02614     fbCombineConjointOutC,
02615     fbCombineConjointOutReverseC,
02616     fbCombineConjointAtopC,
02617     fbCombineConjointAtopReverseC,
02618     fbCombineConjointXorC,
02619 };
02620 
02621 
02622 FbComposeFunctions composeFunctions = {
02623     fbCombineFuncU,
02624     fbCombineFuncC,
02625     fbCombineMaskU
02626 };
02627 
02628 
02629 static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
02630 {
02631     FbBits *bits;
02632     FbStride stride;
02633     int bpp;
02634     int xoff, yoff;
02635     CARD32 color;
02636     CARD32 *end;
02637     fetchPixelProc fetch = fetchPixelProcForPicture(pict);
02638 #ifdef PIXMAN_INDEXED_FORMATS
02639     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
02640 #else
02641     miIndexedPtr indexed = NULL;
02642 #endif
02643 
02644     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
02645     bits += yoff*stride + (xoff*bpp >> FB_SHIFT);
02646 
02647     color = fetch(bits, 0, indexed);
02648 
02649     end = buffer + width;
02650     while (buffer < end)
02651         *buffer++ = color;
02652 }
02653 
02654 static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
02655 {
02656     FbBits *bits;
02657     FbStride stride;
02658     int bpp;
02659     int xoff, yoff;
02660     fetchProc fetch = fetchProcForPicture(pict);
02661 #ifdef PIXMAN_INDEXED_FORMATS
02662     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
02663 #else
02664     miIndexedPtr indexed = NULL;
02665 #endif
02666 
02667     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
02668     x += xoff;
02669     y += yoff;
02670 
02671     bits += y*stride;
02672 
02673     fetch(bits, x, width, buffer, indexed);
02674 }
02675 
02676 #define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :\
02677         ((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
02678 
02679 #ifdef PIXMAN_GRADIENTS
02680 static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread)
02681 {
02682     int ipos = (pos * PICT_GRADIENT_STOPTABLE_SIZE - 1) >> 16;
02683 
02684     /* calculate the actual offset. */
02685     if (ipos < 0 || ipos >= PICT_GRADIENT_STOPTABLE_SIZE) {
02686         if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal) {
02687             ipos = ipos % PICT_GRADIENT_STOPTABLE_SIZE;
02688             ipos = ipos < 0 ? PICT_GRADIENT_STOPTABLE_SIZE + ipos : ipos;
02689 
02690         } else if (spread == RepeatReflect) {
02691             const int limit = PICT_GRADIENT_STOPTABLE_SIZE * 2 - 1;
02692             ipos = ipos % limit;
02693             ipos = ipos < 0 ? limit + ipos : ipos;
02694             ipos = ipos >= PICT_GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
02695 
02696         } else if (spread == RepeatPad) {
02697             if (ipos < 0)
02698                 ipos = 0;
02699             else if (ipos >= PICT_GRADIENT_STOPTABLE_SIZE)
02700                 ipos = PICT_GRADIENT_STOPTABLE_SIZE-1;
02701         } else { /* RepeatNone */
02702             return 0;
02703         }
02704     }
02705 
02706     assert(ipos >= 0);
02707     assert(ipos < PICT_GRADIENT_STOPTABLE_SIZE);
02708 
02709     return pGradient->linear.colorTable[ipos];
02710 }
02711 
02712 static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
02713 {
02714     SourcePictPtr pGradient = pict->pSourcePict;
02715     CARD32 *end = buffer + width;
02716 
02717     if (pGradient->type == SourcePictTypeSolidFill) {
02718         register CARD32 color = pGradient->solidFill.color;
02719         while (buffer < end) {
02720             *buffer++ = color;
02721         }
02722     } else if (pGradient->type == SourcePictTypeLinear) {
02723         PictVector v, unit;
02724         xFixed_32_32 l;
02725         xFixed_48_16 dx, dy, a, b, off;
02726 
02727         v.vector[0] = IntToxFixed(x);
02728         v.vector[1] = IntToxFixed(y);
02729         v.vector[2] = xFixed1;
02730         if (pict->transform) {
02731             if (!PictureTransformPoint3d (pict->transform, &v))
02732                 return;
02733             unit.vector[0] = pict->transform->matrix[0][0];
02734             unit.vector[1] = pict->transform->matrix[1][0];
02735             unit.vector[2] = pict->transform->matrix[2][0];
02736         } else {
02737             unit.vector[0] = xFixed1;
02738             unit.vector[1] = 0;
02739             unit.vector[2] = 0;
02740         }
02741 
02742         dx = pGradient->linear.p2.x - pGradient->linear.p1.x;
02743         dy = pGradient->linear.p2.y - pGradient->linear.p1.y;
02744         l = dx*dx + dy*dy;
02745         if (l != 0) {
02746             a = (dx << 32) / l;
02747             b = (dy << 32) / l;
02748             off = (-a*pGradient->linear.p1.x - b*pGradient->linear.p1.y)>>16;
02749         }
02750         if (l == 0  || (unit.vector[2] == 0 && v.vector[2] == xFixed1)) {
02751             xFixed_48_16 inc, t;
02752             /* affine transformation only */
02753             if (l == 0) {
02754                 t = 0;
02755                 inc = 0;
02756             } else {
02757                 t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off;
02758                 inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16;
02759             }
02760             while (buffer < end) {
02761                 *buffer++ = gradientPixel(pGradient, t, pict->repeat);
02762                 t += inc;
02763             }
02764         } else {
02765             /* projective transformation */
02766             while (buffer < end) {
02767                 xFixed_48_16 t;
02768                 if (v.vector[2] == 0) {
02769                     t = 0;
02770                 } else {
02771                     xFixed_48_16 x, y;
02772                     x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2];
02773                     y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
02774                     t = ((a*x + b*y) >> 16) + off;
02775                 }
02776                 *buffer++ = gradientPixel(pGradient, t, pict->repeat);
02777                 v.vector[0] += unit.vector[0];
02778                 v.vector[1] += unit.vector[1];
02779                 v.vector[2] += unit.vector[2];
02780             }
02781         }
02782     } else {
02783         /* radial or conical */
02784         Bool projective = FALSE;
02785         double cx = 1.;
02786         double cy = 0.;
02787         double cz = 0.;
02788         double rx = x;
02789         double ry = y;
02790         double rz = 1.;
02791 
02792         if (pict->transform) {
02793             PictVector v;
02794             v.vector[0] = IntToxFixed(x);
02795             v.vector[1] = IntToxFixed(y);
02796             v.vector[2] = xFixed1;
02797             if (!PictureTransformPoint3d (pict->transform, &v))
02798                 return;
02799 
02800             cx = pict->transform->matrix[0][0]/65536.;
02801             cy = pict->transform->matrix[1][0]/65536.;
02802             cz = pict->transform->matrix[2][0]/65536.;
02803             rx = v.vector[0]/65536.;
02804             ry = v.vector[1]/65536.;
02805             rz = v.vector[2]/65536.;
02806             projective = pict->transform->matrix[2][0] != 0 || v.vector[2] != xFixed1;
02807         }
02808 
02809         if (pGradient->type == SourcePictTypeRadial) {
02810             if (!projective) {
02811                 rx -= pGradient->radial.fx;
02812                 ry -= pGradient->radial.fy;
02813 
02814                 while (buffer < end) {
02815                     double b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy);
02816                     double c = -(rx*rx + ry*ry);
02817                     double det = (b * b) - (4 * pGradient->radial.a * c);
02818                     double s = (-b + sqrt(det))/(2. * pGradient->radial.a);
02819                     *buffer = gradientPixel(pGradient,
02820                                             (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
02821                                             pict->repeat);
02822                     ++buffer;
02823                     rx += cx;
02824                     ry += cy;
02825                 }
02826             } else {
02827                 while (buffer < end) {
02828                     double x, y;
02829                     double b, c, det, s;
02830                     if (rz != 0) {
02831                         x = rx/rz;
02832                         y = ry/rz;
02833                     } else {
02834                         x = y = 0.;
02835                     }
02836                     x -= pGradient->radial.fx;
02837                     y -= pGradient->radial.fy;
02838                     b = 2*(x*pGradient->radial.dx + y*pGradient->radial.dy);
02839                     c = -(x*x + y*y);
02840                     det = (b * b) - (4 * pGradient->radial.a * c);
02841                     s = (-b + sqrt(det))/(2. * pGradient->radial.a);
02842                     *buffer = gradientPixel(pGradient,
02843                                             (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
02844                                             pict->repeat);
02845                     ++buffer;
02846                     rx += cx;
02847                     ry += cy;
02848                     rz += cz;
02849                 }
02850             }
02851         } else /* SourcePictTypeConical */ {
02852             double a = pGradient->conical.angle/(180.*65536);
02853             if (!projective) {
02854                 rx -= pGradient->conical.center.x/65536.;
02855                 ry -= pGradient->conical.center.y/65536.;
02856 
02857                 while (buffer < end) {
02858                     double angle = atan2(ry, rx) + a;
02859                     *buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
02860                                             pict->repeat);
02861                     ++buffer;
02862                     rx += cx;
02863                     ry += cy;
02864                 }
02865             } else {
02866 
02867                 while (buffer < end) {
02868                     double x, y;
02869                     if (rz != 0) {
02870                         x = rx/rz;
02871                         y = ry/rz;
02872                     } else {
02873                         x = y = 0.;
02874                     }
02875                     x -= pGradient->conical.center.x/65536.;
02876                     y -= pGradient->conical.center.y/65536.;
02877                     double angle = atan2(y, x) + a;
02878                     *buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
02879                                             pict->repeat);
02880                     ++buffer;
02881                     rx += cx;
02882                     ry += cy;
02883                     rz += cz;
02884                 }
02885             }
02886         }
02887     }
02888 }
02889 #endif /* PIXMAN_GRADIENTS */
02890 
02891 
02892 static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
02893 {
02894     FbBits     *bits;
02895     FbStride    stride;
02896     int         bpp;
02897     int         xoff, yoff;
02898     fetchPixelProc   fetch;
02899     PictVector       v;
02900     PictVector  unit;
02901     int         i;
02902     BoxRec    box;
02903 #ifdef PIXMAN_INDEXED_FORMATS
02904     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
02905 #else
02906     miIndexedPtr indexed = NULL;
02907 #endif
02908     Bool projective = FALSE;
02909 
02910     fetch = fetchPixelProcForPicture(pict);
02911 
02912     fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff);
02913     x += xoff;
02914     y += yoff;
02915 
02916     v.vector[0] = IntToxFixed(x);
02917     v.vector[1] = IntToxFixed(y);
02918     v.vector[2] = xFixed1;
02919 
02920     /* when using convolution filters one might get here without a transform */
02921     if (pict->transform) {
02922         if (!PictureTransformPoint3d (pict->transform, &v))
02923             return;
02924         unit.vector[0] = pict->transform->matrix[0][0];
02925         unit.vector[1] = pict->transform->matrix[1][0];
02926         unit.vector[2] = pict->transform->matrix[2][0];
02927     } else {
02928         unit.vector[0] = xFixed1;
02929         unit.vector[1] = 0;
02930         unit.vector[2] = 0;
02931     }
02932     projective = (unit.vector[2] != 0);
02933 
02934     if (pict->filter == PIXMAN_FILTER_NEAREST || pict->filter == PIXMAN_FILTER_FAST)
02935     {
02936         if (pict->repeat == RepeatNormal) {
02937             if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
02938                 box = pict->pCompositeClip->extents;
02939                 for (i = 0; i < width; ++i) {
02940                     if (!v.vector[2]) {
02941                         buffer[i] = 0;
02942                     } else {
02943                         if (projective) {
02944                             y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
02945                             x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
02946                         } else {
02947                             y = MOD(v.vector[1]>>16, pict->pDrawable->height);
02948                             x = MOD(v.vector[0]>>16, pict->pDrawable->width);
02949                         }
02950                         buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
02951                     }
02952                     v.vector[0] += unit.vector[0];
02953                     v.vector[1] += unit.vector[1];
02954                     v.vector[2] += unit.vector[2];
02955                 }
02956             } else {
02957                 for (i = 0; i < width; ++i) {
02958                     if (!v.vector[2]) {
02959                         buffer[i] = 0;
02960                     } else {
02961                         if (projective) {
02962                             y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
02963                             x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
02964                         } else {
02965                             y = MOD(v.vector[1]>>16, pict->pDrawable->height);
02966                             x = MOD(v.vector[0]>>16, pict->pDrawable->width);
02967                         }
02968                         if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box))
02969                             buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
02970                         else
02971                             buffer[i] = 0;
02972                     }
02973                     v.vector[0] += unit.vector[0];
02974                     v.vector[1] += unit.vector[1];
02975                     v.vector[2] += unit.vector[2];
02976                 }
02977             }
02978         } else {
02979             if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
02980                 box = pict->pCompositeClip->extents;
02981                 for (i = 0; i < width; ++i) {
02982                     if (!v.vector[2]) {
02983                         buffer[i] = 0;
02984                     } else {
02985                         if (projective) {
02986                             y = DIV(v.vector[1],v.vector[2]);
02987                             x = DIV(v.vector[0],v.vector[2]);
02988                         } else {
02989                             y = v.vector[1]>>16;
02990                             x = v.vector[0]>>16;
02991                         }
02992                         buffer[i] = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ?
02993                                     0 : fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
02994                     }
02995                     v.vector[0] += unit.vector[0];
02996                     v.vector[1] += unit.vector[1];
02997                     v.vector[2] += unit.vector[2];
02998                 }
02999             } else {
03000                 for (i = 0; i < width; ++i) {
03001                     if (!v.vector[2]) {
03002                         buffer[i] = 0;
03003                     } else {
03004                         if (projective) {
03005                             y = DIV(v.vector[1],v.vector[2]);
03006                             x = DIV(v.vector[0],v.vector[2]);
03007                         } else {
03008                             y = v.vector[1]>>16;
03009                             x = v.vector[0]>>16;
03010                         }
03011                         if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box))
03012                             buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
03013                         else
03014                             buffer[i] = 0;
03015                     }
03016                     v.vector[0] += unit.vector[0];
03017                     v.vector[1] += unit.vector[1];
03018                     v.vector[2] += unit.vector[2];
03019                 }
03020             }
03021         }
03022     } else if (pict->filter == PIXMAN_FILTER_BILINEAR || pict->filter == PIXMAN_FILTER_GOOD || pict->filter == PIXMAN_FILTER_BEST) {
03023         if (pict->repeat == RepeatNormal) {
03024             if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
03025                 box = pict->pCompositeClip->extents;
03026                 for (i = 0; i < width; ++i) {
03027                     if (!v.vector[2]) {
03028                         buffer[i] = 0;
03029                     } else {
03030                         int x1, x2, y1, y2, distx, idistx, disty, idisty;
03031                         FbBits *b;
03032                         CARD32 tl, tr, bl, br, r;
03033                         CARD32 ft, fb;
03034 
03035                         if (projective) {
03036                             xFixed_48_16 div;
03037                             div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
03038                             x1 = div >> 16;
03039                             distx = ((xFixed)div >> 8) & 0xff;
03040                             div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
03041                             y1 = div >> 16;
03042                             disty = ((xFixed)div >> 8) & 0xff;
03043                         } else {
03044                             x1 = v.vector[0] >> 16;
03045                             distx = (v.vector[0] >> 8) & 0xff;
03046                             y1 = v.vector[1] >> 16;
03047                             disty = (v.vector[1] >> 8) & 0xff;
03048                         }
03049                         x2 = x1 + 1;
03050                         y2 = y1 + 1;
03051 
03052                         idistx = 256 - distx;
03053                         idisty = 256 - disty;
03054 
03055                         x1 = MOD (x1, pict->pDrawable->width);
03056                         x2 = MOD (x2, pict->pDrawable->width);
03057                         y1 = MOD (y1, pict->pDrawable->height);
03058                         y2 = MOD (y2, pict->pDrawable->height);
03059 
03060                         b = bits + (y1 + pict->pDrawable->y)*stride;
03061 
03062                         tl = fetch(b, x1 + pict->pDrawable->x, indexed);
03063                         tr = fetch(b, x2 + pict->pDrawable->x, indexed);
03064                         b = bits + (y2 + pict->pDrawable->y)*stride;
03065                         bl = fetch(b, x1 + pict->pDrawable->x, indexed);
03066                         br = fetch(b, x2 + pict->pDrawable->x, indexed);
03067 
03068                         ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
03069                         fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
03070                         r = (((ft * idisty + fb * disty) >> 16) & 0xff);
03071                         ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
03072                         fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
03073                         r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
03074                         ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
03075                         fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
03076                         r |= (((ft * idisty + fb * disty)) & 0xff0000);
03077                         ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
03078                         fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
03079                         r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
03080                         buffer[i] = r;
03081                     }
03082                     v.vector[0] += unit.vector[0];
03083                     v.vector[1] += unit.vector[1];
03084                     v.vector[2] += unit.vector[2];
03085                 }
03086             } else {
03087                 for (i = 0; i < width; ++i) {
03088                     if (!v.vector[2]) {
03089                         buffer[i] = 0;
03090                     } else {
03091                         int x1, x2, y1, y2, distx, idistx, disty, idisty;
03092                         FbBits *b;
03093                         CARD32 tl, tr, bl, br, r;
03094                         CARD32 ft, fb;
03095 
03096                         if (projective) {
03097                             xFixed_48_16 div;
03098                             div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
03099                             x1 = div >> 16;
03100                             distx = ((xFixed)div >> 8) & 0xff;
03101                             div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
03102                             y1 = div >> 16;
03103                             disty = ((xFixed)div >> 8) & 0xff;
03104                         } else {
03105                             x1 = v.vector[0] >> 16;
03106                             distx = (v.vector[0] >> 8) & 0xff;
03107                             y1 = v.vector[1] >> 16;
03108                             disty = (v.vector[1] >> 8) & 0xff;
03109                         }
03110                         x2 = x1 + 1;
03111                         y2 = y1 + 1;
03112 
03113                         idistx = 256 - distx;
03114                         idisty = 256 - disty;
03115 
03116                         x1 = MOD (x1, pict->pDrawable->width);
03117                         x2 = MOD (x2, pict->pDrawable->width);
03118                         y1 = MOD (y1, pict->pDrawable->height);
03119                         y2 = MOD (y2, pict->pDrawable->height);
03120 
03121                         b = bits + (y1 + pict->pDrawable->y)*stride;
03122 
03123                         tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box)
03124                              ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
03125                         tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box)
03126                              ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
03127                         b = bits + (y2 + pict->pDrawable->y)*stride;
03128                         bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box)
03129                              ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
03130                         br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box)
03131                              ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
03132 
03133                         ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
03134                         fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
03135                         r = (((ft * idisty + fb * disty) >> 16) & 0xff);
03136                         ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
03137                         fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
03138                         r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
03139                         ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
03140                         fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
03141                         r |= (((ft * idisty + fb * disty)) & 0xff0000);
03142                         ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
03143                         fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
03144                         r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
03145                         buffer[i] = r;
03146                     }
03147                     v.vector[0] += unit.vector[0];
03148                     v.vector[1] += unit.vector[1];
03149                     v.vector[2] += unit.vector[2];
03150                 }
03151             }
03152         } else {
03153             if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
03154                 box = pict->pCompositeClip->extents;
03155                 for (i = 0; i < width; ++i) {
03156                     if (!v.vector[2]) {
03157                         buffer[i] = 0;
03158                     } else {
03159                         int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
03160                         FbBits *b;
03161                         CARD32 tl, tr, bl, br, r;
03162                         Bool x1_out, x2_out, y1_out, y2_out;
03163                         CARD32 ft, fb;
03164 
03165                         if (projective) {
03166                             xFixed_48_16 div;
03167                             div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
03168                             x1 = div >> 16;
03169                             distx = ((xFixed)div >> 8) & 0xff;
03170                             div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
03171                             y1 = div >> 16;
03172                             disty = ((xFixed)div >> 8) & 0xff;
03173                         } else {
03174                             x1 = v.vector[0] >> 16;
03175                             distx = (v.vector[0] >> 8) & 0xff;
03176                             y1 = v.vector[1] >> 16;
03177                             disty = (v.vector[1] >> 8) & 0xff;
03178                         }
03179                         x2 = x1 + 1;
03180                         y2 = y1 + 1;
03181 
03182                         idistx = 256 - distx;
03183                         idisty = 256 - disty;
03184 
03185                         b = bits + (y1 + pict->pDrawable->y)*stride;
03186                         x_off = x1 + pict->pDrawable->x;
03187 
03188                         x1_out = (x1 < box.x1) | (x1 >= box.x2);
03189                         x2_out = (x2 < box.x1) | (x2 >= box.x2);
03190                         y1_out = (y1 < box.y1) | (y1 >= box.y2);
03191                         y2_out = (y2 < box.y1) | (y2 >= box.y2);
03192 
03193                         tl = x1_out|y1_out ? 0 : fetch(b, x_off, indexed);
03194                         tr = x2_out|y1_out ? 0 : fetch(b, x_off + 1, indexed);
03195                         b += stride;
03196                         bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed);
03197                         br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed);
03198 
03199                         ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
03200                         fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
03201                         r = (((ft * idisty + fb * disty) >> 16) & 0xff);
03202                         ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
03203                         fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
03204                         r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
03205                         ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
03206                         fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
03207                         r |= (((ft * idisty + fb * disty)) & 0xff0000);
03208                         ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
03209                         fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
03210                         r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
03211                         buffer[i] = r;
03212                     }
03213                     v.vector[0] += unit.vector[0];
03214                     v.vector[1] += unit.vector[1];
03215                     v.vector[2] += unit.vector[2];
03216                 }
03217             } else {
03218                 for (i = 0; i < width; ++i) {
03219                     if (!v.vector[2]) {
03220                         buffer[i] = 0;
03221                     } else {
03222                         int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
03223                         FbBits *b;
03224                         CARD32 tl, tr, bl, br, r;
03225                         CARD32 ft, fb;
03226 
03227                         if (projective) {
03228                             xFixed_48_16 div;
03229                             div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
03230                             x1 = div >> 16;
03231                             distx = ((xFixed)div >> 8) & 0xff;
03232                             div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
03233                             y1 = div >> 16;
03234                             disty = ((xFixed)div >> 8) & 0xff;
03235                         } else {
03236                             x1 = v.vector[0] >> 16;
03237                             distx = (v.vector[0] >> 8) & 0xff;
03238                             y1 = v.vector[1] >> 16;
03239                             disty = (v.vector[1] >> 8) & 0xff;
03240                         }
03241                         x2 = x1 + 1;
03242                         y2 = y1 + 1;
03243 
03244                         idistx = 256 - distx;
03245                         idisty = 256 - disty;
03246 
03247                         b = bits + (y1 + pict->pDrawable->y)*stride;
03248                         x_off = x1 + pict->pDrawable->x;
03249 
03250                         tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box)
03251                              ? fetch(b, x_off, indexed) : 0;
03252                         tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box)
03253                              ? fetch(b, x_off + 1, indexed) : 0;
03254                         b += stride;
03255                         bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box)
03256                              ? fetch(b, x_off, indexed) : 0;
03257                         br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box)
03258                              ? fetch(b, x_off + 1, indexed) : 0;
03259 
03260                         ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
03261                         fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
03262                         r = (((ft * idisty + fb * disty) >> 16) & 0xff);
03263                         ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
03264                         fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
03265                         r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
03266                         ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
03267                         fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
03268                         r |= (((ft * idisty + fb * disty)) & 0xff0000);
03269                         ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
03270                         fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
03271                         r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
03272                         buffer[i] = r;
03273                     }
03274                     v.vector[0] += unit.vector[0];
03275                     v.vector[1] += unit.vector[1];
03276                     v.vector[2] += unit.vector[2];
03277                 }
03278             }
03279         }
03280 #ifdef PIXMAN_CONVOLUTION
03281     } else if (pict->filter == PictFilterConvolution) {
03282         xFixed *params = pict->filter_params;
03283         INT32 cwidth = xFixedToInt(params[0]);
03284         INT32 cheight = xFixedToInt(params[1]);
03285         int xoff = params[0] >> 1;
03286         int yoff = params[1] >> 1;
03287         params += 2;
03288         for (i = 0; i < width; ++i) {
03289             if (!v.vector[2]) {
03290                 buffer[i] = 0;
03291             } else {
03292                 int x1, x2, y1, y2, x, y;
03293                 INT32 srtot, sgtot, sbtot, satot;
03294                 xFixed *p = params;
03295 
03296                 if (projective) {
03297                     xFixed_48_16 tmp;
03298                     tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff;
03299                     x1 = xFixedToInt(tmp);
03300                     tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff;
03301                     y1 = xFixedToInt(tmp);
03302                 } else {
03303                     x1 = xFixedToInt(v.vector[0] - xoff);
03304                     y1 = xFixedToInt(v.vector[1] - yoff);
03305                 }
03306                 x2 = x1 + cwidth;
03307                 y2 = y1 + cheight;
03308 
03309                 srtot = sgtot = sbtot = satot = 0;
03310 
03311                 for (y = y1; y < y2; y++) {
03312                     int ty = (pict->repeat == RepeatNormal) ? MOD (y, pict->pDrawable->height) : y;
03313                     for (x = x1; x < x2; x++) {
03314                         if (*p) {
03315                             int tx = (pict->repeat == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
03316                             if (pixman_region_contains_point (pict->pCompositeClip, tx, ty, &box)) {
03317                                 FbBits *b = bits + (ty + pict->pDrawable->y)*stride;
03318                                 CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed);
03319 
03320                                 srtot += Red(c) * *p;
03321                                 sgtot += Green(c) * *p;
03322                                 sbtot += Blue(c) * *p;
03323                                 satot += Alpha(c) * *p;
03324                             }
03325                         }
03326                         p++;
03327                     }
03328                 }
03329 
03330                 if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff;
03331                 if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff;
03332                 if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff;
03333                 if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff;
03334 
03335                 buffer[i] = ((satot << 24) |
03336                              (srtot << 16) |
03337                              (sgtot <<  8) |
03338                              (sbtot       ));
03339             }
03340             v.vector[0] += unit.vector[0];
03341             v.vector[1] += unit.vector[1];
03342             v.vector[2] += unit.vector[2];
03343         }
03344 #endif
03345     }
03346 }
03347 
03348 
03349 static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
03350 {
03351     int i;
03352     CARD32 _alpha_buffer[SCANLINE_BUFFER_LENGTH];
03353     CARD32 *alpha_buffer = _alpha_buffer;
03354 
03355     if (!pict->alphaMap) {
03356         fbFetchTransformed(pict, x, y, width, buffer);
03357         return;
03358     }
03359     
03360     if (width > SCANLINE_BUFFER_LENGTH)
03361         alpha_buffer = (CARD32 *) malloc(width*sizeof(CARD32));
03362     
03363     fbFetchTransformed(pict, x, y, width, buffer);
03364     fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x, y - pict->alphaOrigin.y, width, alpha_buffer);
03365     for (i = 0; i < width; ++i) {
03366         int a = alpha_buffer[i]>>24;
03367         buffer[i] = (a << 24)
03368                  | (div_255(Red(buffer[i]) * a) << 16)
03369                  | (div_255(Green(buffer[i]) * a) << 8)
03370                  | (div_255(Blue(buffer[i]) * a));
03371     }
03372 
03373     if (alpha_buffer != _alpha_buffer)
03374         free(alpha_buffer);
03375 }
03376 
03377 static void fbStore(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
03378 {
03379     FbBits *bits;
03380     FbStride stride;
03381     int bpp;
03382     int xoff, yoff;
03383     storeProc store = storeProcForPicture(pict);
03384 #ifdef PIXMAN_INDEXED_FORMATS
03385     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
03386 #else
03387     miIndexedPtr indexed = NULL;
03388 #endif
03389 
03390     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
03391     x += xoff;
03392     y += yoff;
03393 
03394     bits += y*stride;
03395     store(bits, buffer, x, width, indexed);
03396 }
03397 
03398 static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
03399 {
03400     FbBits *bits, *alpha_bits;
03401     FbStride stride, astride;
03402     int bpp, abpp;
03403     int xoff, yoff;
03404     int ax, ay;
03405     storeProc store;
03406     storeProc astore;
03407 #ifdef PIXMAN_INDEXED_FORMATS
03408     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
03409 #else
03410     miIndexedPtr indexed = NULL;
03411 #endif
03412     miIndexedPtr aindexed;
03413 
03414     if (!pict->alphaMap) {
03415         fbStore(pict, x, y, width, buffer);
03416         return;
03417     }
03418 
03419     store = storeProcForPicture(pict);
03420     astore = storeProcForPicture(pict->alphaMap);
03421 #ifdef PIXMAN_INDEXED_FORMATS
03422     aindexed = (miIndexedPtr) pict->alphaMap->pFormat->index.devPrivate;
03423 #else
03424     aindexed = NULL;
03425 #endif
03426 
03427     ax = x;
03428     ay = y;
03429 
03430     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
03431     x += xoff;
03432     y += yoff;
03433     fbGetDrawable (pict->alphaMap->pDrawable, alpha_bits, astride, abpp, xoff, yoff);
03434     ax += xoff;
03435     ay += yoff;
03436 
03437     bits       += y*stride;
03438     alpha_bits += (ay - pict->alphaOrigin.y)*astride;
03439 
03440 
03441     store(bits, buffer, x, width, indexed);
03442     astore(alpha_bits, buffer, ax - pict->alphaOrigin.x, width, aindexed);
03443 }
03444 
03445 typedef void (*scanStoreProc)(PicturePtr , int , int , int , CARD32 *);
03446 typedef void (*scanFetchProc)(PicturePtr , int , int , int , CARD32 *);
03447 
03448 static void
03449 fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
03450 {
03451     CARD32 *src_buffer = scanline_buffer;
03452     CARD32 *dest_buffer = src_buffer + data->width;
03453     int i;
03454     scanStoreProc store;
03455     scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
03456 
03457     if (data->op == PIXMAN_OPERATOR_CLEAR)
03458         fetchSrc = NULL;
03459     else if (!data->src->pDrawable) {
03460 #ifdef PIXMAN_GRADIENTS
03461         if (data->src->pSourcePict)
03462             fetchSrc = fbFetchSourcePict;
03463 #endif
03464     } else if (data->src->alphaMap)
03465         fetchSrc = fbFetchExternalAlpha;
03466     else if (data->src->repeat == RepeatNormal &&
03467              data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1)
03468         fetchSrc = fbFetchSolid;
03469 #ifdef PIXMAN_CONVOLUTION
03470     else if (!data->src->transform && data->src->filter != PictFilterConvolution)
03471         fetchSrc = fbFetch;
03472 #else
03473     else if (!data->src->transform)
03474         fetchSrc = fbFetch;
03475 #endif
03476     else
03477         fetchSrc = fbFetchTransformed;
03478 
03479     if (data->mask && data->op != PIXMAN_OPERATOR_CLEAR) {
03480         if (!data->mask->pDrawable) {
03481 #ifdef PIXMAN_GRADIENTS
03482             if (data->mask->pSourcePict)
03483                 fetchMask = fbFetchSourcePict;
03484 #endif
03485         } else if (data->mask->alphaMap)
03486             fetchMask = fbFetchExternalAlpha;
03487         else if (data->mask->repeat == RepeatNormal
03488                  && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
03489             fetchMask = fbFetchSolid;
03490 #ifdef PIXMAN_CONVOLUTION
03491         else if (!data->mask->transform && data->mask->filter != PictFilterConvolution)
03492             fetchMask = fbFetch;
03493 #else
03494         else if (!data->mask->transform)
03495             fetchMask = fbFetch;
03496 #endif
03497         else
03498             fetchMask = fbFetchTransformed;
03499     } else {
03500         fetchMask = NULL;
03501     }
03502 
03503     if (data->dest->alphaMap) {
03504         fetchDest = fbFetchExternalAlpha;
03505         store = fbStoreExternalAlpha;
03506     } else {
03507         fetchDest = fbFetch;
03508         store = fbStore;
03509     }
03510     if (data->op == PIXMAN_OPERATOR_CLEAR || data->op == PIXMAN_OPERATOR_SRC)
03511         fetchDest = NULL;
03512 
03513     if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format_code)) {
03514         CARD32 *mask_buffer = dest_buffer + data->width;
03515         CombineFuncC compose = composeFunctions.combineC[data->op];
03516         if (!compose)
03517             return;
03518 
03519         for (i = 0; i < data->height; ++i)
03520         {
03521             /* fill first half of scanline with source */
03522             fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, src_buffer);
03523             fetchMask(data->mask, data->xMask, data->yMask + i, data->width, mask_buffer);
03524 
03525             /* fill dest into second half of scanline */
03526             if (fetchDest)
03527                 fetchDest(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
03528 
03529             /* blend */
03530             compose(dest_buffer, src_buffer, mask_buffer, data->width);
03531 
03532             /* write back */
03533             store(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
03534         }
03535     } else {
03536 
03537         CombineFuncU compose = composeFunctions.combineU[data->op];
03538         if (!compose)
03539             return;
03540 
03541         if (fetchSrc == fbFetchSolid && (!fetchMask || fetchMask == fbFetchSolid)) {
03542             fetchSrc(data->src, data->xSrc, data->ySrc, data->width, src_buffer);
03543             if (fetchMask) {
03544                 fetchMask(data->mask, data->xMask, data->yMask, data->width, dest_buffer);
03545                 composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width);
03546             }
03547             fetchSrc = NULL;
03548             fetchMask = NULL;
03549         }
03550 
03551         for (i = 0; i < data->height; ++i) {
03552             /* fill first half of scanline with source */
03553             if (fetchSrc) {
03554                 fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, src_buffer);
03555 
03556                 /* add in mask */
03557                 if (fetchMask) {
03558                     fetchMask(data->mask, data->xMask, data->yMask + i, data->width, dest_buffer);
03559                     composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width);
03560                 }
03561             }
03562 
03563             /* fill dest into second half of scanline */
03564             if (fetchDest)
03565                 fetchDest(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
03566 
03567             /* blend */
03568             compose(dest_buffer, src_buffer, data->width);
03569 
03570             /* write back */
03571             store(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
03572         }
03573     }
03574 }
03575 
03576 void
03577 pixman_compositeGeneral (pixman_operator_t       op,
03578                   PicturePtr       pSrc,
03579                   PicturePtr       pMask,
03580                   PicturePtr       pDst,
03581                   INT16     xSrc,
03582                   INT16     ySrc,
03583                   INT16     xMask,
03584                   INT16     yMask,
03585                   INT16     xDst,
03586                   INT16     yDst,
03587                   CARD16    width,
03588                   CARD16    height)
03589 {
03590     pixman_region16_t *region;
03591     int                  n;
03592     BoxPtr        pbox;
03593     Bool          srcRepeat = FALSE;
03594     Bool          maskRepeat = FALSE;
03595     int                  w, h;
03596     CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3];
03597     CARD32 *scanline_buffer = _scanline_buffer;
03598     FbComposeData compose_data;
03599     
03600     if (pSrc->pDrawable)
03601         srcRepeat = pSrc->repeat == RepeatNormal && !pSrc->transform
03602                     && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
03603 
03604     if (pMask && pMask->pDrawable)
03605        maskRepeat = pMask->repeat == RepeatNormal && !pMask->transform
03606                      && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1);
03607 
03608     if (op == PIXMAN_OPERATOR_OVER && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format_code) && !pSrc->alphaMap)
03609         op = PIXMAN_OPERATOR_SRC;
03610 
03611     region = pixman_region_create();
03612     pixman_region_union_rect (region, region, xDst, yDst, width, height);
03613 
03614     if (!FbComputeCompositeRegion (region,
03615                                pSrc,
03616                                pMask,
03617                                pDst,
03618                                xSrc,
03619                                ySrc,
03620                                xMask,
03621                                yMask,
03622                                xDst,
03623                                yDst,
03624                                width,
03625                                height))
03626            return;
03627 
03628     compose_data.op = op;
03629     compose_data.src = pSrc;
03630     compose_data.mask = pMask;
03631     compose_data.dest = pDst;
03632     if (width > SCANLINE_BUFFER_LENGTH)
03633         scanline_buffer = (CARD32 *) malloc(width * 3 * sizeof(CARD32));
03634 
03635     n = pixman_region_num_rects (region);
03636     pbox = pixman_region_rects (region);
03637     while (n--)
03638     {
03639        h = pbox->y2 - pbox->y1;
03640        compose_data.ySrc = pbox->y1 - yDst + ySrc;
03641        compose_data.yMask = pbox->y1 - yDst + yMask;
03642        compose_data.yDest = pbox->y1;
03643        while (h)
03644        {
03645            compose_data.height = h;
03646            w = pbox->x2 - pbox->x1;
03647            compose_data.xSrc = pbox->x1 - xDst + xSrc;
03648            compose_data.xMask = pbox->x1 - xDst + xMask;
03649            compose_data.xDest = pbox->x1;
03650            if (maskRepeat)
03651            {
03652               compose_data.yMask = mod (compose_data.yMask, pMask->pDrawable->height);
03653               if (compose_data.height > pMask->pDrawable->height - compose_data.yMask)
03654                   compose_data.height = pMask->pDrawable->height - compose_data.yMask;
03655            }
03656            if (srcRepeat)
03657            {
03658               compose_data.ySrc = mod (compose_data.ySrc, pSrc->pDrawable->height);
03659               if (compose_data.height > pSrc->pDrawable->height - compose_data.ySrc)
03660                   compose_data.height = pSrc->pDrawable->height - compose_data.ySrc;
03661            }
03662            while (w)
03663            {
03664               compose_data.width = w;
03665               if (maskRepeat)
03666               {
03667                   compose_data.xMask = mod (compose_data.xMask, pMask->pDrawable->width);
03668                   if (compose_data.width > pMask->pDrawable->width - compose_data.xMask)
03669                      compose_data.width = pMask->pDrawable->width - compose_data.xMask;
03670               }
03671               if (srcRepeat)
03672               {
03673                   compose_data.xSrc = mod (compose_data.xSrc, pSrc->pDrawable->width);
03674                   if (compose_data.width > pSrc->pDrawable->width - compose_data.xSrc)
03675                      compose_data.width = pSrc->pDrawable->width - compose_data.xSrc;
03676               }
03677               fbCompositeRect(&compose_data, scanline_buffer);
03678               w -= compose_data.width;
03679               compose_data.xSrc += compose_data.width;
03680               compose_data.xMask += compose_data.width;
03681               compose_data.xDest += compose_data.width;
03682            }
03683            h -= compose_data.height;
03684            compose_data.ySrc += compose_data.height;
03685            compose_data.yMask += compose_data.height;
03686            compose_data.yDest += compose_data.height;
03687        }
03688        pbox++;
03689     }
03690     pixman_region_destroy (region);
03691 
03692     if (scanline_buffer != _scanline_buffer)
03693         free(scanline_buffer);
03694 }
03695 
03696 #endif