📄 fbpict.c
字号:
CompositeFunc func = NULL; Bool srcRepeat = pSrc->pDrawable && pSrc->repeat == RepeatNormal; Bool maskRepeat = FALSE; Bool srcTransform = pSrc->transform != 0; Bool maskTransform = 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 (srcRepeat && srcTransform && pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1) srcTransform = FALSE; if (pMask && pMask->pDrawable) { xMask += pMask->pDrawable->x; yMask += pMask->pDrawable->y; maskRepeat = pMask->repeat == RepeatNormal; maskTransform = pMask->transform != 0;#ifdef PIXMAN_CONVOLUTION if (pMask->filter == PictFilterConvolution) maskTransform = TRUE;#endif maskAlphaMap = pMask->alphaMap != 0; if (maskRepeat && maskTransform && pMask->pDrawable->width == 1 && pMask->pDrawable->height == 1) maskTransform = FALSE; } if (pSrc->pDrawable && (!pMask || pMask->pDrawable) && !srcTransform && !maskTransform && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap#ifdef PIXMAN_CONVOLUTION && (pSrc->filter != PictFilterConvolution) && (!pMask || pMask->filter != PictFilterConvolution)#endif ) switch (op) { case PIXMAN_OPERATOR_OVER: if (pMask) { if (srcRepeat && pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1) { if (PICT_FORMAT_COLOR(pSrc->format_code)) { switch (pMask->format_code) { case PICT_a8: switch (pDst->format_code) { 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; } break; case PICT_a8r8g8b8: if (pMask->componentAlpha) { switch (pDst->format_code) { 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; } } else { switch (pDst->format_code) { case PICT_r5g6b5: func = fbCompositeSolidMask_nx8888x0565; break; } } break; case PICT_a8b8g8r8: if (pMask->componentAlpha) { switch (pDst->format_code) { 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; } } else { switch (pDst->format_code) { case PICT_b5g6r5: func = fbCompositeSolidMask_nx8888x0565; break; } } break; case PICT_a1: switch (pDst->format_code) { 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; } } } if (func != pixman_compositeGeneral) srcRepeat = FALSE; } else /* has mask and non-repeating source */ { if (pSrc->pDrawable == pMask->pDrawable && xSrc == xMask && ySrc == yMask && !pMask->componentAlpha) { /* source == mask: non-premultiplied data */ switch (pSrc->format_code) { case PICT_x8b8g8r8: switch (pMask->format_code) { case PICT_a8r8g8b8: case PICT_a8b8g8r8: switch (pDst->format_code) { 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; } break; } break; case PICT_x8r8g8b8: switch (pMask->format_code) { case PICT_a8r8g8b8: case PICT_a8b8g8r8: switch (pDst->format_code) { 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;#endif break; } break; } break; } break; } else { /* non-repeating source, repeating mask => translucent window */ if (maskRepeat && pMask->pDrawable->width == 1 && pMask->pDrawable->height == 1) { switch (pSrc->format_code) { case PICT_r5g6b5: case PICT_b5g6r5: if (pDst->format_code == pSrc->format_code) func = fbCompositeTrans_0565xnx0565; break; case PICT_r8g8b8: case PICT_b8g8r8: if (pDst->format_code == pSrc->format_code) func = fbCompositeTrans_0888xnx0888; break;#ifdef USE_MMX case PICT_x8r8g8b8: case PICT_x8b8g8r8: if (pDst->format_code == pSrc->format_code && pMask->format_code == PICT_a8 && fbHaveMMX()) func = fbCompositeSrc_x888x8x8888mmx; break;#if 0 /* This case fails rendercheck for me */ case PICT_a8r8g8b8: if ((pDst->format == PICT_a8r8g8b8 || pDst->format == PICT_x8r8g8b8) && pMask->format == PICT_a8 && fbHaveMMX()) func = fbCompositeSrc_8888x8x8888mmx; break;#endif case PICT_a8b8g8r8: if ((pDst->format_code == PICT_a8b8g8r8 || pDst->format_code == PICT_x8b8g8r8) && pMask->format_code == PICT_a8 && fbHaveMMX()) func = fbCompositeSrc_8888x8x8888mmx; break;#endif } if (func != pixman_compositeGeneral) maskRepeat = FALSE; } } } } else /* no mask */ { if (srcRepeat && pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1) { /* no mask and repeating source */ switch (pSrc->format_code) { case PICT_a8r8g8b8: switch (pDst->format_code) { 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; } break; } } else { /* * Formats without alpha bits are just Copy with Over */ if (pSrc->format_code == pDst->format_code && !PICT_FORMAT_A(pSrc->format_code)) {#ifdef USE_MMX if (fbHaveMMX() && (pSrc->format_code == PICT_x8r8g8b8 || pSrc->format_code == PICT_x8b8g8r8)) func = fbCompositeCopyAreammx; else#endif func = fbCompositeSrcSrc_nxn; } else switch (pSrc->format_code) { case PICT_a8r8g8b8: switch (pDst->format_code) { 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; } break; case PICT_a8b8g8r8: switch (pDst->format_code) { 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; } break; } } } break; case PIXMAN_OPERATOR_ADD: if (pMask == 0) { switch (pSrc->format_code) { case PICT_a8r8g8b8: switch (pDst->format_code) { case PICT_a8r8g8b8:#ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrcAdd_8888x8888mmx; else#endif func = fbCompositeSrcAdd_8888x8888; break; } break; case PICT_a8b8g8r8: switch (pDst->format_code) { case PICT_a8b8g8r8:#ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrcAdd_8888x8888mmx; else#endif func = fbCompositeSrcAdd_8888x8888; break; } break; case PICT_a8: switch (pDst->format_code) { case PICT_a8:#ifdef USE_MMX if (fbHaveMMX()) func = fbCompositeSrcAdd_8000x8000mmx; else#endif func = fbCompositeSrcAdd_8000x8000; break; } break; case PICT_a1: switch (pDst->format_code) { case PICT_a1: func = fbCompositeSrcAdd_1000x1000; break; } break; } } break; case PIXMAN_OPERATOR_SRC: if (pMask) {#ifdef USE_MMX if (srcRepeat && pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1) { if (pMask->format_code == PICT_a8) { switch (pDst->format_code) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: case PICT_a8b8g8r8: case PICT_x8b8g8r8: if (fbHaveMMX()) func = fbCompositeSolidMaskSrc_nx8x8888mmx; break; } } }#endif } else { if (pSrc->format_code == pDst->format_code) {#ifdef USE_MMX if (pSrc->pDrawable != pDst->pDrawable && (PICT_FORMAT_BPP (pSrc->format_code) == 16 || PICT_FORMAT_BPP (pSrc->format_code) == 32)) func = fbCompositeCopyAreammx; else#endif func = fbCompositeSrcSrc_nxn; } } break; default: /* For any operator not specifically handled above we default out to the general code. */ func = NULL; } if (!func) { /* no fast path, use the general code */ pixman_compositeGeneral(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); return; } /* if we are transforming, we handle repeats in IcFetch[a]_transform */ if (srcTransform) srcRepeat = 0; if (maskTransform) maskRepeat = 0; region = pixman_region_create(); pixman_region_union_rect (region, region, xDst, yDst, width, height); if (!FbComputeCompositeRegion (region, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) return; n = pixman_region_num_rects (region); pbox = pixman_region_rects (region); while (n--) { h = pbox->y2 - pbox->y1; y_src = pbox->y1 - yDst + ySrc; y_msk = pbox->y1 - yDst + yMask; y_dst = pbox->y1; while (h) { h_this = h; w = pbox->x2 - pbox->x1; x_src = pbox->x1 - xDst + xSrc; x_msk = pbox->x1 - xDst + xMask; x_dst = pbox->x1; if (maskRepeat) { y_msk = mod (y_msk, pMask->pDrawable->height); if (h_this > pMask->pDrawable->height - y_msk) h_this = pMask->pDrawable->height - y_msk; } if (srcRepeat) { y_src = mod (y_src, pSrc->pDrawable->height); if (h_this > pSrc->pDrawable->height - y_src) h_this = pSrc->pDrawable->height - y_src; } while (w) { w_this = w; if (maskRepeat) { x_msk = mod (x_msk, pMask->pDrawable->width); if (w_this > pMask->pDrawable->width - x_msk) w_this = pMask->pDrawable->width - x_msk; } if (srcRepeat) { x_src = mod (x_src, pSrc->pDrawable->width); if (w_this > pSrc->pDrawable->width - x_src) w_this = pSrc->pDrawable->width - x_src; } (*func) (op, pSrc, pMask, pDst, x_src, y_src, x_msk, y_msk, x_dst, y_dst, w_this, h_this); w -= w_this; x_src += w_this; x_msk += w_this; x_dst += w_this; } h -= h_this; y_src += h_this; y_msk += h_this; y_dst += h_this; } pbox++; } pixman_region_destroy (region);}slim_hidden_def(pixman_composite);/* 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(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__)enum CPUFeatures { NoFeatures = 0, MMX = 0x1, MMX_Extensions = 0x2, SSE = 0x6, SSE2 = 0x8, CMOV = 0x10};static unsigned int detectCPUFeatures(void) { unsigned int result, features; 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 1f\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" ); features = 0; 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 1f\n" "mov $0x80000001, %%eax\n" "cpuid\n" "1:\n" "pop %%ebx\n" "mov %%edx, %0\n" : "=r" (result) : : "%eax", "%ecx", "%edx" ); if (result & (1<<22)) features |= MMX_Extensions; } } return features;}BoolfbHaveMMX (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 /* USE_MMX && !amd64 */#endif /* RENDER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -