📄 fblin32alpha.c
字号:
/* * 32bpp (With Alpha) Linear Video Driver for Microwindows * * Written by Koninklijke Philips Electronics N.V. * Based on the existing 32bpp (no alpha) driver: * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com> * Inspired from Ben Pfaff's BOGL <pfaffben@debian.org> * * Portions contributed by Koninklijke Philips Electronics N.V. * These portions are Copyright 2002, 2003 Koninklijke Philips Electronics * N.V. All Rights Reserved. These portions are licensed under the * terms of the Mozilla Public License, version 1.1, or, at your * option, the GNU General Public License version 2.0. Please see * the file "ChangeLog" for documentation regarding these * contributions. *//*#define NDEBUG*/#include <assert.h>#include <string.h>#include "device.h"#include "fb.h"typedef unsigned long MW_U32;typedef long MW_S32;/* It's a lot easier to treat the buffer as an array of bytes when * alpha blending, and an array of MW_U32 otherwise. However, * without some care, that would not be portable due to endian * issues. * * These macros help solve this problem. They define which bytes * in memory correspond to which field. */#if MW_CPU_BIG_ENDIAN#define MWI_BYTE_OFFSET_ALPHA 0#define MWI_BYTE_OFFSET_R 1#define MWI_BYTE_OFFSET_G 2#define MWI_BYTE_OFFSET_B 3#else#define MWI_BYTE_OFFSET_ALPHA 3#define MWI_BYTE_OFFSET_R 2#define MWI_BYTE_OFFSET_G 1#define MWI_BYTE_OFFSET_B 0#endif/* Calc linelen and mmap size, return 0 on fail*/static intlinear32a_init(PSD psd){#ifndef NDEBUG /* * Check the endian mode of the CPU matches what was specified * in the config file at compile time. * * (Also validates that the various #defines are internally * consistent). */ unsigned long endian_check = COLOR2PIXEL8888(MWARGB(1, 2, 3, 4)); assert(((char *) (&endian_check))[MWI_BYTE_OFFSET_ALPHA] == 1); assert(((char *) (&endian_check))[MWI_BYTE_OFFSET_R] == 2); assert(((char *) (&endian_check))[MWI_BYTE_OFFSET_G] == 3); assert(((char *) (&endian_check))[MWI_BYTE_OFFSET_B] == 4);#endif if (!psd->size) { psd->size = psd->yres * psd->linelen; /* convert linelen from byte to pixel len for bpp 16, 24, 32 */ psd->linelen /= 4; } return 1;}/* * For alpha blending, we use 2 different 'alpha' values: * * psa = specified alpha. 0 <= psa <= 255 * * psa_inv = 256 - psa * This flips the direction of alpha, so it's * backwards from it's usual meaning. * This is because some of the equations below are most * easily written with source and dest interchanged * (since we can split the source color into it's * components beforehand) *//* Set pixel at x, y, to pixelval c*/static voidlinear32a_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c){ ADDR32 addr = psd->addr; assert(addr != 0); assert(x >= 0 && x < psd->xres); assert(y >= 0 && y < psd->yres); addr += x + y * psd->linelen; DRAWON; if (gr_mode == MWMODE_COPY) { *addr = c; } else if (gr_mode <= MWMODE_SIMPLE_MAX) { applyOp(gr_mode, c, addr, ADDR32); } else { MW_S32 psr, psg, psb; MW_S32 psa, psa_inv; MW_U32 pd; psa = (((MW_U32) c) >> 24); switch (gr_mode) { case MWMODE_SRC_OVER: if (psa == 255) { *addr = c; } else if (psa != 0) { psa_inv = 256 - psa; psr = (MW_S32) (c & 0x00FF0000UL); psg = (MW_S32) (c & 0x0000FF00UL); psb = (MW_S32) (c & 0x000000FFUL); pd = *addr; *addr = ((MW_U32) (((((MW_S32) (pd & 0x00FF0000UL) - psr) * psa_inv) >> 8) + psr) & 0x00FF0000UL) | ((MW_U32) (((((MW_S32) (pd & 0x0000FF00UL) - psg) * psa_inv) >> 8) + psg) & 0x0000FF00UL) | ((MW_U32) (((((MW_S32) (pd & 0x000000FFUL) - psb) * psa_inv) >> 8) + psb) & 0x000000FFUL) | (((psa << 24) + ((pd & 0xFF000000UL) >> 8) * (MW_U32) psa_inv) & 0xFF000000UL); } break; case MWMODE_SRC_IN: case MWMODE_SRC_ATOP: case MWMODE_DST_OVER: case MWMODE_DST_IN: case MWMODE_DST_ATOP: case MWMODE_SRC_OUT: case MWMODE_DST_OUT: case MWMODE_PORTERDUFF_XOR: /* FIXME!!! */ break; default: assert(0); } } DRAWOFF;}/* Read pixel at x, y*/static MWPIXELVALlinear32a_readpixel(PSD psd, MWCOORD x, MWCOORD y){ ADDR32 addr = psd->addr; assert(addr != 0); assert(x >= 0 && x < psd->xres); assert(y >= 0 && y < psd->yres); return addr[x + y * psd->linelen];}/* Draw horizontal line from x1,y to x2,y including final point*/static voidlinear32a_drawhorzline(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y, MWPIXELVAL c){ ADDR32 addr = psd->addr; assert(addr != 0); assert(x1 >= 0 && x1 < psd->xres); assert(x2 >= 0 && x2 < psd->xres); assert(x2 >= x1); assert(y >= 0 && y < psd->yres); addr += x1 + y * psd->linelen; DRAWON; if (gr_mode == MWMODE_COPY) { /* FIXME: memsetl(dst, c, x2-x1+1) */ while (x1++ <= x2) *addr++ = c; } else if (gr_mode <= MWMODE_SIMPLE_MAX) { while (x1++ <= x2) { applyOp(gr_mode, c, addr, ADDR32); ++addr; } } else { MW_S32 psr, psg, psb; MW_S32 psa, psa_inv; MW_U32 pd; MW_U32 cache_input, cache_output; psa = (((MW_U32) c) >> 24); switch (gr_mode) { case MWMODE_SRC_OVER: if (psa == 255) { while (x1++ <= x2) *addr++ = c; } else if (psa != 0) { psa_inv = 256 - psa; psr = (MW_S32) (c & 0x00FF0000UL); psg = (MW_S32) (c & 0x0000FF00UL); psb = (MW_S32) (c & 0x000000FFUL); pd = *addr; cache_input = pd; cache_output = ((MW_U32) (((((MW_S32) (pd & 0x00FF0000UL) - psr) * psa_inv) >> 8) + psr) & 0x00FF0000UL) | ((MW_U32) (((((MW_S32) (pd & 0x0000FF00UL) - psg) * psa_inv) >> 8) + psg) & 0x0000FF00UL) | ((MW_U32) (((((MW_S32) (pd & 0x000000FFUL) - psb) * psa_inv) >> 8) + psb) & 0x000000FFUL) | (((psa << 24) + ((pd & 0xFF000000UL) >> 8) * ((MW_U32) psa_inv)) & 0xFF000000UL); *addr++ = cache_output; while (++x1 <= x2) { pd = *addr; if (cache_input != pd) { cache_input = pd; cache_output = ((MW_U32) (((((MW_S32) (pd & 0x00FF0000UL) - psr) * psa_inv) >> 8) + psr) & 0x00FF0000UL) | ((MW_U32) (((((MW_S32) (pd & 0x0000FF00UL) - psg) * psa_inv) >> 8) + psg) & 0x0000FF00UL) | ((MW_U32) (((((MW_S32) (pd & 0x000000FFUL) - psb) * psa_inv) >> 8) + psb) & 0x000000FFUL) | (((psa << 24) + ((pd & 0xFF000000UL) >> 8) * ((MW_U32) psa_inv)) & 0xFF000000UL); } *addr++ = cache_output; } } break; case MWMODE_SRC_IN: case MWMODE_SRC_ATOP: case MWMODE_DST_OVER: case MWMODE_DST_IN: case MWMODE_DST_ATOP: case MWMODE_SRC_OUT: case MWMODE_DST_OUT: case MWMODE_PORTERDUFF_XOR: /* FIXME!!! */ break; default: assert(0); } } DRAWOFF;}/* Draw a vertical line from x,y1 to x,y2 including final point*/static voidlinear32a_drawvertline(PSD psd, MWCOORD x, MWCOORD y1, MWCOORD y2, MWPIXELVAL c){ ADDR32 addr = psd->addr; int linelen = psd->linelen; assert(addr != 0); assert(x >= 0 && x < psd->xres); assert(y1 >= 0 && y1 < psd->yres); assert(y2 >= 0 && y2 < psd->yres); assert(y2 >= y1); DRAWON; addr += x + y1 * linelen; if (gr_mode == MWMODE_COPY) { while (y1++ <= y2) { *addr = c; addr += linelen; } } else if (gr_mode <= MWMODE_SIMPLE_MAX) { while (y1++ <= y2) { applyOp(gr_mode, c, addr, ADDR32); addr += linelen; } } else { MW_S32 psr, psg, psb; MW_S32 psa, psa_inv; MW_U32 pd; MW_U32 cache_input, cache_output; psa = (((MW_U32) c) >> 24); switch (gr_mode) { case MWMODE_SRC_OVER: if (psa == 255) { while (y1++ <= y2) { *addr = c; addr += linelen; } } else if (psa != 0) { psa_inv = 256 - psa; psr = (MW_S32) (c & 0x00FF0000UL); psg = (MW_S32) (c & 0x0000FF00UL); psb = (MW_S32) (c & 0x000000FFUL); pd = *addr; cache_input = pd; cache_output = ((MW_U32) (((((MW_S32) (pd & 0x00FF0000UL) - psr) * psa_inv) >> 8) + psr) & 0x00FF0000UL) | ((MW_U32) (((((MW_S32) (pd & 0x0000FF00UL) - psg) * psa_inv) >> 8) + psg) & 0x0000FF00UL) | ((MW_U32) (((((MW_S32) (pd & 0x000000FFUL) - psb) * psa_inv) >> 8) + psb) & 0x000000FFUL) | (((psa << 24) + ((pd & 0xFF000000UL) >> 8) * ((MW_U32) psa_inv)) & 0xFF000000UL); *addr = cache_output; addr += linelen; while (++y1 <= y2) { pd = *addr; if (cache_input != pd) { cache_input = pd; cache_output = ((MW_U32) (((((MW_S32) (pd & 0x00FF0000UL) - psr) * psa_inv) >> 8) + psr) & 0x00FF0000UL) | ((MW_U32) (((((MW_S32) (pd & 0x0000FF00UL) - psg) * psa_inv) >> 8) + psg) & 0x0000FF00UL) | ((MW_U32) (((((MW_S32) (pd & 0x000000FFUL) - psb) * psa_inv) >> 8) + psb) & 0x000000FFUL) | (((psa << 24) + ((pd & 0xFF000000UL) >> 8) * ((MW_U32) psa_inv)) & 0xFF000000UL); } *addr = cache_output; addr += linelen; } } break; case MWMODE_SRC_IN: case MWMODE_SRC_ATOP: case MWMODE_DST_OVER: case MWMODE_DST_IN: case MWMODE_DST_ATOP: case MWMODE_SRC_OUT: case MWMODE_DST_OUT: case MWMODE_PORTERDUFF_XOR: /* FIXME!!! */ break; default: assert(0); } } DRAWOFF;}/* srccopy bitblt*/static voidlinear32a_blit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD w, MWCOORD h, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long op){ ADDR8 dst8, src8; ADDR32 dst = dstpsd->addr; ADDR32 src = srcpsd->addr; int i; int dlinelen = dstpsd->linelen; int slinelen = srcpsd->linelen; int dlinelen_minus_w4; int slinelen_minus_w4;#if ALPHABLEND unsigned int alpha;#endif assert(dst != 0); assert(dstx >= 0 && dstx < dstpsd->xres); assert(dsty >= 0 && dsty < dstpsd->yres); assert(w > 0); assert(h > 0); assert(src != 0); assert(srcx >= 0 && srcx < srcpsd->xres); assert(srcy >= 0 && srcy < srcpsd->yres); assert(dstx + w <= dstpsd->xres); assert(dsty + h <= dstpsd->yres); assert(srcx + w <= srcpsd->xres); assert(srcy + h <= srcpsd->yres); DRAWON; dst += dstx + dsty * dlinelen; src += srcx + srcy * slinelen;#if ALPHABLEND if ((op & MWROP_EXTENSION) != MWROP_BLENDCONSTANT) goto stdblit; alpha = op & 0xff; src8 = (ADDR8) src; dst8 = (ADDR8) dst; dlinelen_minus_w4 = (dlinelen - w) * 4; slinelen_minus_w4 = (slinelen - w) * 4; while (--h >= 0) { for (i = 0; i < w; ++i) { register unsigned long s; register unsigned long d; s = src8[MWI_BYTE_OFFSET_R]; d = dst8[MWI_BYTE_OFFSET_R]; dst8[MWI_BYTE_OFFSET_R] = (unsigned char) (((s - d) * alpha) >> 8) + d; s = src8[MWI_BYTE_OFFSET_G]; d = dst8[MWI_BYTE_OFFSET_G]; dst8[MWI_BYTE_OFFSET_G] = (unsigned char) (((s - d) * alpha) >> 8) + d; s = src8[MWI_BYTE_OFFSET_B]; d = dst8[MWI_BYTE_OFFSET_B]; dst8[MWI_BYTE_OFFSET_B] = (unsigned char) (((s - d) * alpha) >> 8) + d; s = src8[MWI_BYTE_OFFSET_ALPHA]; d = dst8[MWI_BYTE_OFFSET_ALPHA]; dst8[MWI_BYTE_OFFSET_ALPHA] = (unsigned char) (((s - d) * alpha) >> 8) + d; dst8 += 4; src8 += 4; } dst8 += dlinelen_minus_w4; src8 += slinelen_minus_w4; } DRAWOFF; return; stdblit:#endif if (op == MWROP_COPY) { /* copy from bottom up if dst in src rectangle */ /* memmove is used to handle x case */ if (srcy < dsty) { src += (h - 1) * slinelen; dst += (h - 1) * dlinelen; slinelen *= -1; dlinelen *= -1; } while (--h >= 0) { /* a _fast_ memmove is a _must_ in this routine */ memmove(dst, src, w << 2); dst += dlinelen; src += slinelen; } } else if (MWROP_TO_MODE(op) <= MWMODE_SIMPLE_MAX) { for (i = 0; i < w; ++i) { applyOp(MWROP_TO_MODE(op), *src, dst, ADDR32); ++src; ++dst; } dst += dlinelen - w; src += slinelen - w; } else if (MWROP_TO_MODE(op) == MWMODE_SRC_OVER) { src8 = (ADDR8) src; dst8 = (ADDR8) dst; while (h--) { for (i = w; --i >= 0;) { register int a; register int s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -