-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Daniel Amelang schreef: > On 5/23/07, Koen Kooi <[EMAIL PROTECTED]> wrote: >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> Daniel Amelang schreef: >> >>> If slow pixbuf rendering were a problem, you may be interested in a >>> patch I submitted recently to xorg that speeded up pixbuf rendering on >>> R5G6B5 framebuffers by 3.4x : >>> >>> http://lists.freedesktop.org/archives/xorg/2007-April/024286.html >>> >>> That speedup was measured on a N800, but the neo1973 should see >>> similar improvement. >> I gave the testapp and patch a spin: >> >> ipaq hx4700: >> >> unpatched Xw100: 6.04 FPS >> patched Xw100: 6.04 FPS >> unpatched Xfbdev: 6.04 FPS >> patched Xfbdev: 6.04 FPS >> >> ipaq h2200: >> >> unpatched Xfbdev: 4.18 FPS >> patched Xfbdev: 4.17 FPS >> >> Any clues why the patch doesn't seem to have an effect? > > Assuming you didn't make any errors in applying the patch and getting > the patched server compiled and up and running (I do have faith in you > :), it's likely that for your combination of Gdk+Xserver+hardware, the > test program doesn't hit the exact same composite case > (fbCompositeSrc_8888RevNPx0565) as it does on my N800.
gtk 2.10.12 + xserver-xorg 1.2.0, built as kdrive. > Easiest way to tell that would to add a couple ErrorF calls in > fbpict.c to see what functions are called. ErrorF messages get spat > out to stderr, if I remember correctly. > > You didn't happen to apply that patch by hand, did you? I can think of > a couple tricky places that might have tripped you up if you did. > Especially the part about adding the new function to the fbComposite > "switch case of doom". Care to send me your patched fbpict.c? attached. regards, Koen -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Darwin) iD8DBQFGU/9cMkyGM64RGpERAst6AJwKBtrF10aXL64PINzp64UeS2MG5ACeKOc3 plSyJuOetHvaqxZyw8OfCTM= =N20f -----END PGP SIGNATURE-----
/* * * Copyright © 2000 SuSE, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of SuSE not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. SuSE makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Keith Packard, SuSE, Inc. */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif #include <string.h> #include "fb.h" #ifdef RENDER #include "picturestr.h" #include "mipict.h" #include "fbpict.h" #include "fbmmx.h" typedef void (*CompositeFunc) (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); CARD32 fbOver (CARD32 x, CARD32 y) { CARD16 a = ~x >> 24; CARD16 t; CARD32 m,n,o,p; m = FbOverU(x,y,0,a,t); n = FbOverU(x,y,8,a,t); o = FbOverU(x,y,16,a,t); p = FbOverU(x,y,24,a,t); return m|n|o|p; } CARD32 fbOver24 (CARD32 x, CARD32 y) { CARD16 a = ~x >> 24; CARD16 t; CARD32 m,n,o; m = FbOverU(x,y,0,a,t); n = FbOverU(x,y,8,a,t); o = FbOverU(x,y,16,a,t); return m|n|o; } CARD32 fbIn (CARD32 x, CARD8 y) { CARD16 a = y; CARD16 t; CARD32 m,n,o,p; m = FbInU(x,0,a,t); n = FbInU(x,8,a,t); o = FbInU(x,16,a,t); p = FbInU(x,24,a,t); return m|n|o|p; } /* * Naming convention: * * opSRCxMASKxDST */ void fbCompositeSolidMask_nx8x8888 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 src, srca; CARD32 *dstLine, *dst, d, dstMask; CARD8 *maskLine, *mask, m; FbStride dstStride, maskStride; CARD16 w; fbComposeGetSolid(pSrc, src, pDst->format); dstMask = FbFullMask (pDst->pDrawable->depth); srca = src >> 24; if (src == 0) return; fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; mask = maskLine; maskLine += maskStride; w = width; while (w--) { m = *mask++; if (m == 0xff) { if (srca == 0xff) *dst = src & dstMask; else *dst = fbOver (src, *dst) & dstMask; } else if (m) { d = fbIn (src, m); *dst = fbOver (d, *dst) & dstMask; } dst++; } } } void fbCompositeSolidMask_nx8888x8888C (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 src, srca; CARD32 *dstLine, *dst, d, dstMask; CARD32 *maskLine, *mask, ma; FbStride dstStride, maskStride; CARD16 w; CARD32 m, n, o, p; fbComposeGetSolid(pSrc, src, pDst->format); dstMask = FbFullMask (pDst->pDrawable->depth); srca = src >> 24; if (src == 0) return; fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; mask = maskLine; maskLine += maskStride; w = width; while (w--) { ma = *mask++; if (ma == 0xffffffff) { if (srca == 0xff) *dst = src & dstMask; else *dst = fbOver (src, *dst) & dstMask; } else if (ma) { d = *dst; #define FbInOverC(src,srca,msk,dst,i,result) { \ CARD16 __a = FbGet8(msk,i); \ CARD32 __t, __ta; \ CARD32 __i; \ __t = FbIntMult (FbGet8(src,i), __a,__i); \ __ta = (CARD8) ~FbIntMult (srca, __a,__i); \ __t = __t + FbIntMult(FbGet8(dst,i),__ta,__i); \ __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \ result = __t << (i); \ } FbInOverC (src, srca, ma, d, 0, m); FbInOverC (src, srca, ma, d, 8, n); FbInOverC (src, srca, ma, d, 16, o); FbInOverC (src, srca, ma, d, 24, p); *dst = m|n|o|p; } dst++; } } } void fbCompositeSolidMask_nx8x0888 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 src, srca; CARD8 *dstLine, *dst; CARD32 d; CARD8 *maskLine, *mask, m; FbStride dstStride, maskStride; CARD16 w; fbComposeGetSolid(pSrc, src, pDst->format); srca = src >> 24; if (src == 0) return; fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 3); fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; mask = maskLine; maskLine += maskStride; w = width; while (w--) { m = *mask++; if (m == 0xff) { if (srca == 0xff) d = src; else { d = Fetch24(dst); d = fbOver24 (src, d); } Store24(dst,d); } else if (m) { d = fbOver24 (fbIn(src,m), Fetch24(dst)); Store24(dst,d); } dst += 3; } } } void fbCompositeSolidMask_nx8x0565 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 src, srca; CARD16 *dstLine, *dst; CARD32 d; CARD8 *maskLine, *mask, m; FbStride dstStride, maskStride; CARD16 w; fbComposeGetSolid(pSrc, src, pDst->format); srca = src >> 24; if (src == 0) return; fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; mask = maskLine; maskLine += maskStride; w = width; while (w--) { m = *mask++; if (m == 0xff) { if (srca == 0xff) d = src; else { d = *dst; d = fbOver24 (src, cvt0565to8888(d)); } *dst = cvt8888to0565(d); } else if (m) { d = *dst; d = fbOver24 (fbIn(src,m), cvt0565to8888(d)); *dst = cvt8888to0565(d); } dst++; } } } void fbCompositeSolidMask_nx8888x0565C (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 src, srca; CARD16 src16; CARD16 *dstLine, *dst; CARD32 d; CARD32 *maskLine, *mask, ma; FbStride dstStride, maskStride; CARD16 w; CARD32 m, n, o; fbComposeGetSolid(pSrc, src, pDst->format); srca = src >> 24; if (src == 0) return; src16 = cvt8888to0565(src); fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; mask = maskLine; maskLine += maskStride; w = width; while (w--) { ma = *mask++; if (ma == 0xffffffff) { if (srca == 0xff) { *dst = src16; } else { d = *dst; d = fbOver24 (src, cvt0565to8888(d)); *dst = cvt8888to0565(d); } } else if (ma) { d = *dst; d = cvt0565to8888(d); FbInOverC (src, srca, ma, d, 0, m); FbInOverC (src, srca, ma, d, 8, n); FbInOverC (src, srca, ma, d, 16, o); d = m|n|o; *dst = cvt8888to0565(d); } dst++; } } } void fbCompositeSrc_8888x8888 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 *dstLine, *dst, dstMask; CARD32 *srcLine, *src, s; FbStride dstStride, srcStride; CARD8 a; CARD16 w; fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); dstMask = FbFullMask (pDst->pDrawable->depth); while (height--) { dst = dstLine; dstLine += dstStride; src = srcLine; srcLine += srcStride; w = width; while (w--) { s = *src++; a = s >> 24; if (a == 0xff) *dst = s & dstMask; else if (a) *dst = fbOver (s, *dst) & dstMask; dst++; } } } void fbCompositeSrc_8888x0888 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD8 *dstLine, *dst; CARD32 d; CARD32 *srcLine, *src, s; CARD8 a; FbStride dstStride, srcStride; CARD16 w; fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 3); fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; src = srcLine; srcLine += srcStride; w = width; while (w--) { s = *src++; a = s >> 24; if (a) { if (a == 0xff) d = s; else d = fbOver24 (s, Fetch24(dst)); Store24(dst,d); } dst += 3; } } } void fbCompositeSrc_8888x0565 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD16 *dstLine, *dst; CARD32 d; CARD32 *srcLine, *src, s; CARD8 a; FbStride dstStride, srcStride; CARD16 w; fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; src = srcLine; srcLine += srcStride; w = width; while (w--) { s = *src++; a = s >> 24; if (a) { if (a == 0xff) d = s; else { d = *dst; d = fbOver24 (s, cvt0565to8888(d)); } *dst = cvt8888to0565(d); } dst++; } } } void fbCompositeSrc_0565x0565 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD16 *dstLine, *dst; CARD16 *srcLine, *src; FbStride dstStride, srcStride; CARD16 w; fbComposeGetStart (pSrc, xSrc, ySrc, CARD16, srcStride, srcLine, 1); fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; src = srcLine; srcLine += srcStride; w = width; while (w--) *dst++ = *src++; } } #define cvt8888Revto0565(s) ((((s) >> 19) & 0x001f) | \ (((s) >> 5) & 0x07e0) | \ (((s) << 8) & 0xf800)) #define FbOverU_8888RevNPx565(s, d) \ \ /* Extract alpha */ \ s_a = (s) >> 24; \ \ /* Extract r8g8b8 color channels */ \ s_r = ( (s) & 0xff); \ s_g = (((s) >> 8) & 0xff); \ s_b = (((s) >> 16) & 0xff); \ \ /* Extract r5g6b5 color channels */ \ d_r = ((d) >> 8) & 0xf8; \ d_g = ((d) >> 3) & 0xfc; \ d_b = ((d) << 3) & 0xf8; \ \ /* Use the higher bits of the channel to fill out the bottom */ \ d_r |= (d_r >> 5); \ d_g |= (d_g >> 6); \ d_b |= (d_b >> 5); \ \ /* Blend */ \ d_r = (s_r - d_r) * s_a + (d_r << 8); \ d_g = (s_g - d_g) * s_a + (d_g << 8); \ d_b = (s_b - d_b) * s_a + (d_b << 8); \ \ /* Pack result as r5g6b5 */ \ (d) = (d_r & 0xf800) | ((d_g & 0xfc00) >> 5) | (d_b >> 11) void fbCompositeSrc_8888RevNPx0565 (FbComposeData *params) { CARD16 *dstLine, *dst; CARD32 *srcLine, *src; FbStride dstStride, srcStride; int w, h; fbComposeGetStart (params->src, params->xSrc, params->ySrc, CARD32, srcStride, srcLine, 1); fbComposeGetStart (params->dest, params->xDest, params->yDest, CARD16, dstStride, dstLine, 1); h = params->height; while (h--) { CARD32 s1, s2, s3, s4; int d_r, d_g, d_b, s_r, s_g, s_b, s_a; CARD32 *dst_2px_wide; src = srcLine; srcLine += srcStride; dst_2px_wide = (CARD32 *) dstLine; dstLine += dstStride; w = params->width - 4; while (w >= 0) { s1 = *src; s2 = *(src + 1); s3 = *(src + 2); s4 = *(src + 3); w -= 4; src += 4; /* Check if the next 4 pixels are opaque */ if ((s1 & s2 & s3 & s4) > 0xfeffffff) { /* In this case, we just perform a SOURCE for all 4 pixels */ #if X_BYTE_ORDER == X_BIG_ENDIAN *dst_2px_wide++ = (cvt8888Revto0565 (s1) << 16) | cvt8888Revto0565 (s2); *dst_2px_wide++ = (cvt8888Revto0565 (s3) << 16) | cvt8888Revto0565 (s4); #else *dst_2px_wide++ = cvt8888Revto0565 (s1) | (cvt8888Revto0565 (s2) << 16); *dst_2px_wide++ = cvt8888Revto0565 (s3) | (cvt8888Revto0565 (s4) << 16); #endif } /* Next, check if the next 4 pixels have any alpha in them at all */ else if ((s1 | s2 | s3 | s4) > 0x00ffffff) { /* In which case, we perform OVER on each one of them */ CARD32 d1, d2, d3, d4; #if X_BYTE_ORDER == X_BIG_ENDIAN d1 = (*dst_2px_wide >> 16); d2 = (*dst_2px_wide & 0xffff); FbOverU_8888RevNPx565 (s1, d1); FbOverU_8888RevNPx565 (s2, d2); *dst_2px_wide++ = (d1 << 16) | d2; #else d2 = (*dst_2px_wide >> 16); d1 = (*dst_2px_wide & 0xffff); FbOverU_8888RevNPx565 (s1, d1); FbOverU_8888RevNPx565 (s2, d2); *dst_2px_wide++ = d1 | (d2 << 16); #endif #if X_BYTE_ORDER == X_BIG_ENDIAN d3 = (*dst_2px_wide >> 16); d4 = (*dst_2px_wide & 0xffff); FbOverU_8888RevNPx565 (s3, d3); FbOverU_8888RevNPx565 (s4, d4); *dst_2px_wide++ = (d3 << 16) | d4; #else d4 = (*dst_2px_wide >> 16); d3 = (*dst_2px_wide & 0xffff); FbOverU_8888RevNPx565 (s3, d3); FbOverU_8888RevNPx565 (s4, d4); *dst_2px_wide++ = d3 | (d4 << 16); #endif } else { /* Do nothing, since the source pixels are all transparent */ dst_2px_wide += 2; } } /* Deal with left over pixels */ for (dst = (CARD16 *) dst_2px_wide; w > -4; w--) { CARD32 d = *dst; CARD32 s = *src++; FbOverU_8888RevNPx565 (s, d); *dst++ = d; } } } void fbCompositeSrcAdd_8000x8000 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD8 *dstLine, *dst; CARD8 *srcLine, *src; FbStride dstStride, srcStride; CARD16 w; CARD8 s, d; CARD16 t; fbComposeGetStart (pSrc, xSrc, ySrc, CARD8, srcStride, srcLine, 1); fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; src = srcLine; srcLine += srcStride; w = width; while (w--) { s = *src++; if (s) { if (s != 0xff) { d = *dst; t = d + s; s = t | (0 - (t >> 8)); } *dst = s; } dst++; } } } void fbCompositeSrcAdd_8888x8888 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 *dstLine, *dst; CARD32 *srcLine, *src; FbStride dstStride, srcStride; CARD16 w; CARD32 s, d; CARD16 t; CARD32 m,n,o,p; fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); while (height--) { dst = dstLine; dstLine += dstStride; src = srcLine; srcLine += srcStride; w = width; while (w--) { s = *src++; if (s) { if (s != 0xffffffff) { d = *dst; if (d) { m = FbAdd(s,d,0,t); n = FbAdd(s,d,8,t); o = FbAdd(s,d,16,t); p = FbAdd(s,d,24,t); s = m|n|o|p; } } *dst = s; } dst++; } } } void fbCompositeSrcAdd_1000x1000 (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { FbBits *dstBits, *srcBits; FbStride dstStride, srcStride; int dstBpp, srcBpp; int dstXoff, dstYoff; int srcXoff, srcYoff; fbGetDrawable(pSrc->pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); fbGetDrawable(pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); fbBlt (srcBits + srcStride * (ySrc + srcYoff), srcStride, xSrc + srcXoff, dstBits + dstStride * (yDst + dstYoff), dstStride, xDst + dstXoff, width, height, GXor, FB_ALLONES, srcBpp, FALSE, FALSE); } void fbCompositeSolidMask_nx1xn (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { FbBits *dstBits; FbStip *maskBits; FbStride dstStride, maskStride; int dstBpp, maskBpp; int dstXoff, dstYoff; int maskXoff, maskYoff; FbBits src; fbComposeGetSolid(pSrc, src, pDst->format); if ((src & 0xff000000) != 0xff000000) { fbCompositeGeneral (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); return; } fbGetStipDrawable (pMask->pDrawable, maskBits, maskStride, maskBpp, maskXoff, maskYoff); fbGetDrawable (pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); switch (dstBpp) { case 32: break; case 24: break; case 16: src = cvt8888to0565(src); break; } src = fbReplicatePixel (src, dstBpp); fbBltOne (maskBits + maskStride * (yMask + maskYoff), maskStride, xMask + maskXoff, dstBits + dstStride * (yDst + dstYoff), dstStride, (xDst + dstXoff) * dstBpp, dstBpp, width * dstBpp, height, 0x0, src, FB_ALLONES, 0x0); } # define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) void fbComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { RegionRec region; int n; BoxPtr pbox; CompositeFunc func = NULL; Bool srcRepeat = pSrc->pDrawable && pSrc->repeat; Bool maskRepeat = FALSE; Bool srcAlphaMap = pSrc->alphaMap != 0; Bool maskAlphaMap = FALSE; Bool dstAlphaMap = pDst->alphaMap != 0; int x_msk, y_msk, x_src, y_src, x_dst, y_dst; int w, h, w_this, h_this; #ifdef USE_MMX static Bool mmx_setup = FALSE; if (!mmx_setup) { fbComposeSetupMMX(); mmx_setup = TRUE; } #endif xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; if (pSrc->pDrawable) { xSrc += pSrc->pDrawable->x; ySrc += pSrc->pDrawable->y; } if (pMask && pMask->pDrawable) { xMask += pMask->pDrawable->x; yMask += pMask->pDrawable->y; maskRepeat = pMask->repeat == RepeatNormal; maskAlphaMap = pMask->alphaMap != 0; } if (pSrc->pDrawable && (!pMask || pMask->pDrawable) && !pSrc->transform && !(pMask && pMask->transform) && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap && (pSrc->filter != PictFilterConvolution) && (!pMask || pMask->filter != PictFilterConvolution)) switch (op) { case PictOpSrc: #ifdef USE_MMX if (!pMask && pSrc->format == pDst->format && pSrc->format != PICT_a8 && pSrc->pDrawable != pDst->pDrawable) { func = fbCompositeCopyAreammx; } #endif break; case PictOpOver: if (pMask) { if (fbCanGetSolid(pSrc) && !maskRepeat) { srcRepeat = FALSE; if (PICT_FORMAT_COLOR(pSrc->format)) { switch (pMask->format) { case PICT_a8: switch (pDst->format) { case PICT_r5g6b5: case PICT_b5g6r5: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSolidMask_nx8x0565mmx; else #endif func = fbCompositeSolidMask_nx8x0565; break; case PICT_r8g8b8: case PICT_b8g8r8: func = fbCompositeSolidMask_nx8x0888; break; case PICT_a8r8g8b8: case PICT_x8r8g8b8: case PICT_a8b8g8r8: case PICT_x8b8g8r8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSolidMask_nx8x8888mmx; else #endif func = fbCompositeSolidMask_nx8x8888; break; default: break; } break; case PICT_a8r8g8b8: if (pMask->componentAlpha) { switch (pDst->format) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSolidMask_nx8888x8888Cmmx; else #endif func = fbCompositeSolidMask_nx8888x8888C; break; case PICT_r5g6b5: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSolidMask_nx8888x0565Cmmx; else #endif func = fbCompositeSolidMask_nx8888x0565C; break; default: break; } } break; case PICT_a8b8g8r8: if (pMask->componentAlpha) { switch (pDst->format) { case PICT_a8b8g8r8: case PICT_x8b8g8r8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSolidMask_nx8888x8888Cmmx; else #endif func = fbCompositeSolidMask_nx8888x8888C; break; case PICT_b5g6r5: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSolidMask_nx8888x0565Cmmx; else #endif func = fbCompositeSolidMask_nx8888x0565C; break; default: break; } } break; case PICT_a1: switch (pDst->format) { case PICT_r5g6b5: case PICT_b5g6r5: case PICT_r8g8b8: case PICT_b8g8r8: case PICT_a8r8g8b8: case PICT_x8r8g8b8: case PICT_a8b8g8r8: case PICT_x8b8g8r8: func = fbCompositeSolidMask_nx1xn; break; default: break; } break; default: break; } default: break; } } else if (! srcRepeat) /* has mask and non-repeating source */ { if (pSrc->pDrawable == pMask->pDrawable && xSrc == xMask && ySrc == yMask && !pMask->componentAlpha && !maskRepeat) { /* source == mask: non-premultiplied data */ switch (pSrc->format) { case PICT_x8b8g8r8: switch (pMask->format) { case PICT_a8r8g8b8: case PICT_a8b8g8r8: switch (pDst->format) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrc_8888RevNPx8888mmx; #endif break; case PICT_r5g6b5: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrc_8888RevNPx0565mmx; #endif break; default: break; } break; default: break; } break; case PICT_x8r8g8b8: switch (pMask->format) { case PICT_a8r8g8b8: case PICT_a8b8g8r8: switch (pDst->format) { case PICT_a8b8g8r8: case PICT_x8b8g8r8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrc_8888RevNPx8888mmx; #endif break; case PICT_r5g6b5: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrc_8888RevNPx0565mmx; else #endif func = fbCompositeSrc_8888RevNPx0565; break; default: break; } break; default: break; } break; default: break; } break; } else { /* non-repeating source, repeating mask => translucent window */ if (fbCanGetSolid(pMask)) { if (pSrc->format == PICT_x8r8g8b8 && pDst->format == PICT_x8r8g8b8 && pMask->format == PICT_a8) { #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrc_8888x8x8888mmx; #endif } } } } } else /* no mask */ { if (fbCanGetSolid(pSrc)) { /* no mask and repeating source */ switch (pSrc->format) { case PICT_a8r8g8b8: switch (pDst->format) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: #ifdef USE_MMX if (fbHaveMMX()) { srcRepeat = FALSE; func = fbCompositeSolid_nx8888mmx; } #endif break; case PICT_r5g6b5: #ifdef USE_MMX if (fbHaveMMX()) { srcRepeat = FALSE; func = fbCompositeSolid_nx0565mmx; } #endif break; default: break; } break; default: break; } } else if (! srcRepeat) { switch (pSrc->format) { case PICT_a8r8g8b8: switch (pDst->format) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrc_8888x8888mmx; else #endif func = fbCompositeSrc_8888x8888; break; case PICT_r8g8b8: func = fbCompositeSrc_8888x0888; break; case PICT_r5g6b5: func = fbCompositeSrc_8888x0565; break; default: break; } break; case PICT_x8r8g8b8: switch (pDst->format) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeCopyAreammx; #endif break; default: break; } case PICT_x8b8g8r8: switch (pDst->format) { case PICT_a8b8g8r8: case PICT_x8b8g8r8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeCopyAreammx; #endif break; default: break; } break; case PICT_a8b8g8r8: switch (pDst->format) { case PICT_a8b8g8r8: case PICT_x8b8g8r8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrc_8888x8888mmx; else #endif func = fbCompositeSrc_8888x8888; break; case PICT_b8g8r8: func = fbCompositeSrc_8888x0888; break; case PICT_b5g6r5: func = fbCompositeSrc_8888x0565; break; default: break; } break; case PICT_r5g6b5: switch (pDst->format) { case PICT_r5g6b5: func = fbCompositeSrc_0565x0565; break; default: break; } break; case PICT_b5g6r5: switch (pDst->format) { case PICT_b5g6r5: func = fbCompositeSrc_0565x0565; break; default: break; } break; default: break; } } } break; case PictOpAdd: if (pMask == 0) { switch (pSrc->format) { case PICT_a8r8g8b8: switch (pDst->format) { case PICT_a8r8g8b8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrcAdd_8888x8888mmx; else #endif func = fbCompositeSrcAdd_8888x8888; break; default: break; } break; case PICT_a8b8g8r8: switch (pDst->format) { case PICT_a8b8g8r8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrcAdd_8888x8888mmx; else #endif func = fbCompositeSrcAdd_8888x8888; break; default: break; } break; case PICT_a8: switch (pDst->format) { case PICT_a8: #ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrcAdd_8000x8000mmx; else #endif func = fbCompositeSrcAdd_8000x8000; break; default: break; } break; case PICT_a1: switch (pDst->format) { case PICT_a1: func = fbCompositeSrcAdd_1000x1000; break; default: break; } break; default: break; } } break; } if (!func) { /* no fast path, use the general code */ fbCompositeGeneral(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); return; } if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) return; n = REGION_NUM_RECTS (®ion); pbox = REGION_RECTS (®ion); while (n--) { h = pbox->y2 - pbox->y1; y_src = pbox->y1 - yDst + ySrc; y_msk = pbox->y1 - yDst + yMask; y_dst = pbox->y1; while (h) { h_this = h; w = pbox->x2 - pbox->x1; x_src = pbox->x1 - xDst + xSrc; x_msk = pbox->x1 - xDst + xMask; x_dst = pbox->x1; if (maskRepeat) { y_msk = mod (y_msk - pMask->pDrawable->y, pMask->pDrawable->height); if (h_this > pMask->pDrawable->height - y_msk) h_this = pMask->pDrawable->height - y_msk; y_msk += pMask->pDrawable->y; } if (srcRepeat) { y_src = mod (y_src - pSrc->pDrawable->y, pSrc->pDrawable->height); if (h_this > pSrc->pDrawable->height - y_src) h_this = pSrc->pDrawable->height - y_src; y_src += pSrc->pDrawable->y; } while (w) { w_this = w; if (maskRepeat) { x_msk = mod (x_msk - pMask->pDrawable->x, pMask->pDrawable->width); if (w_this > pMask->pDrawable->width - x_msk) w_this = pMask->pDrawable->width - x_msk; x_msk += pMask->pDrawable->x; } if (srcRepeat) { x_src = mod (x_src - pSrc->pDrawable->x, pSrc->pDrawable->width); if (w_this > pSrc->pDrawable->width - x_src) w_this = pSrc->pDrawable->width - x_src; x_src += pSrc->pDrawable->x; } (*func) (op, pSrc, pMask, pDst, x_src, y_src, x_msk, y_msk, x_dst, y_dst, w_this, h_this); w -= w_this; x_src += w_this; x_msk += w_this; x_dst += w_this; } h -= h_this; y_src += h_this; y_msk += h_this; y_dst += h_this; } pbox++; } REGION_UNINIT (pDst->pDrawable->pScreen, ®ion); } #endif /* RENDER */ Bool fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) { #ifdef RENDER PictureScreenPtr ps; if (!miPictureInit (pScreen, formats, nformats)) return FALSE; ps = GetPictureScreen(pScreen); ps->Composite = fbComposite; ps->Glyphs = miGlyphs; ps->CompositeRects = miCompositeRects; ps->RasterizeTrapezoid = fbRasterizeTrapezoid; ps->AddTraps = fbAddTraps; ps->AddTriangles = fbAddTriangles; #endif /* RENDER */ return TRUE; } #ifdef USE_MMX /* The CPU detection code needs to be in a file not compiled with * "-mmmx -msse", as gcc would generate CMOV instructions otherwise * that would lead to SIGILL instructions on old CPUs that don't have * it. */ #if !defined(__amd64__) && !defined(__x86_64__) #ifdef HAVE_GETISAX #include <sys/auxv.h> #endif enum CPUFeatures { NoFeatures = 0, MMX = 0x1, MMX_Extensions = 0x2, SSE = 0x6, SSE2 = 0x8, CMOV = 0x10 }; static unsigned int detectCPUFeatures(void) { unsigned int features = 0; unsigned int result; #ifdef HAVE_GETISAX if (getisax(&result, 1)) { if (result & AV_386_CMOV) features |= CMOV; if (result & AV_386_MMX) features |= MMX; if (result & AV_386_AMD_MMX) features |= MMX_Extensions; if (result & AV_386_SSE) features |= SSE; if (result & AV_386_SSE2) features |= SSE2; } #else char vendor[13]; vendor[0] = 0; vendor[12] = 0; /* see p. 118 of amd64 instruction set manual Vol3 */ /* We need to be careful about the handling of %ebx and * %esp here. We can't declare either one as clobbered * since they are special registers (%ebx is the "PIC * register" holding an offset to global data, %esp the * stack pointer), so we need to make sure they have their * original values when we access the output operands. */ __asm__ ("pushf\n" "pop %%eax\n" "mov %%eax, %%ecx\n" "xor $0x00200000, %%eax\n" "push %%eax\n" "popf\n" "pushf\n" "pop %%eax\n" "mov $0x0, %%edx\n" "xor %%ecx, %%eax\n" "jz 1\n" "mov $0x00000000, %%eax\n" "push %%ebx\n" "cpuid\n" "mov %%ebx, %%eax\n" "pop %%ebx\n" "mov %%eax, %1\n" "mov %%edx, %2\n" "mov %%ecx, %3\n" "mov $0x00000001, %%eax\n" "push %%ebx\n" "cpuid\n" "pop %%ebx\n" "1:\n" "mov %%edx, %0\n" : "=r" (result), "=m" (vendor[0]), "=m" (vendor[4]), "=m" (vendor[8]) : : "%eax", "%ecx", "%edx" ); if (result) { /* result now contains the standard feature bits */ if (result & (1 << 15)) features |= CMOV; if (result & (1 << 23)) features |= MMX; if (result & (1 << 25)) features |= SSE; if (result & (1 << 26)) features |= SSE2; if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) { /* check for AMD MMX extensions */ unsigned int result; __asm__("push %%ebx\n" "mov $0x80000000, %%eax\n" "cpuid\n" "xor %%edx, %%edx\n" "cmp $0x1, %%eax\n" "jge 2\n" "mov $0x80000001, %%eax\n" "cpuid\n" "2:\n" "pop %%ebx\n" "mov %%edx, %0\n" : "=r" (result) : : "%eax", "%ecx", "%edx" ); if (result & (1<<22)) features |= MMX_Extensions; } } #endif /* HAVE_GETISAX */ return features; } Bool fbHaveMMX (void) { static Bool initialized = FALSE; static Bool mmx_present; if (!initialized) { unsigned int features = detectCPUFeatures(); mmx_present = (features & (MMX|MMX_Extensions)) == (MMX|MMX_Extensions); initialized = TRUE; } return mmx_present; } #endif /* __amd64__ */ #endif
_______________________________________________ Performance-list mailing list Performance-list@gnome.org http://mail.gnome.org/mailman/listinfo/performance-list