You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
TinyX/fb/fbcompose.c

4285 lines
117 KiB
C

/*
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* 2005 Lars Knoll & Zack Rusin, Trolltech
*
* 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 Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "fb.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "picturestr.h"
#include "mipict.h"
#include "fbpict.h"
#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
#define SCANLINE_BUFFER_LENGTH 2048
typedef FASTCALL void (*fetchProc) (const FbBits * bits, int x, int width,
CARD32 *buffer, miIndexedPtr indexed);
/*
* All of the fetch functions
*/
static FASTCALL void
fbFetch_a8r8g8b8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
memcpy(buffer, (const CARD32 *) bits + x, width * sizeof(CARD32));
}
static FASTCALL void
fbFetch_x8r8g8b8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD32 *pixel = (const CARD32 *) bits + x;
const CARD32 *end = pixel + width;
while (pixel < end) {
*buffer++ = *pixel++ | 0xff000000;
}
}
static FASTCALL void
fbFetch_a8b8g8r8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD32 *pixel = (CARD32 *) bits + x;
const CARD32 *end = pixel + width;
while (pixel < end) {
*buffer++ = ((*pixel & 0xff00ff00) |
((*pixel >> 16) & 0xff) | ((*pixel & 0xff) << 16));
++pixel;
}
}
static FASTCALL void
fbFetch_x8b8g8r8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD32 *pixel = (CARD32 *) bits + x;
const CARD32 *end = pixel + width;
while (pixel < end) {
*buffer++ = 0xff000000 |
((*pixel & 0x0000ff00) |
((*pixel >> 16) & 0xff) | ((*pixel & 0xff) << 16));
++pixel;
}
}
static FASTCALL void
fbFetch_r8g8b8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + 3 * x;
const CARD8 *end = pixel + 3 * width;
while (pixel < end) {
CARD32 b = Fetch24(pixel) | 0xff000000;
pixel += 3;
*buffer++ = b;
}
}
static FASTCALL void
fbFetch_b8g8r8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + 3 * x;
const CARD8 *end = pixel + 3 * width;
while (pixel < end) {
CARD32 b = 0xff000000;
#if IMAGE_BYTE_ORDER == MSBFirst
b |= (*pixel++);
b |= (*pixel++ << 8);
b |= (*pixel++ << 16);
#else
b |= (*pixel++ << 16);
b |= (*pixel++ << 8);
b |= (*pixel++);
#endif
*buffer++ = b;
}
}
static FASTCALL void
fbFetch_r5g6b5(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r = (((p) << 3) & 0xf8) |
(((p) << 5) & 0xfc00) | (((p) << 8) & 0xf80000);
r |= (r >> 5) & 0x70007;
r |= (r >> 6) & 0x300;
*buffer++ = 0xff000000 | r;
}
}
static FASTCALL void
fbFetch_b5g6r5(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b;
b = ((p & 0xf800) | ((p & 0xe000) >> 5)) >> 8;
g = ((p & 0x07e0) | ((p & 0x0600) >> 6)) << 5;
r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
*buffer++ = (0xff000000 | r | g | b);
}
}
static FASTCALL void
fbFetch_a1r5g5b5(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b, a;
a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24;
r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9;
g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2;
*buffer++ = (a | r | g | b);
}
}
static FASTCALL void
fbFetch_x1r5g5b5(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b;
r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9;
g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2;
*buffer++ = (0xff000000 | r | g | b);
}
}
static FASTCALL void
fbFetch_a1b5g5r5(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b, a;
a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24;
b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7;
g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
*buffer++ = (a | r | g | b);
}
}
static FASTCALL void
fbFetch_x1b5g5r5(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b;
b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7;
g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
*buffer++ = (0xff000000 | r | g | b);
}
}
static FASTCALL void
fbFetch_a4r4g4b4(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b, a;
a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16;
r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
b = ((p & 0x000f) | ((p & 0x000f) << 4));
*buffer++ = (a | r | g | b);
}
}
static FASTCALL void
fbFetch_x4r4g4b4(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b;
r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
b = ((p & 0x000f) | ((p & 0x000f) << 4));
*buffer++ = (0xff000000 | r | g | b);
}
}
static FASTCALL void
fbFetch_a4b4g4r4(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b, a;
a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16;
b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4;
g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16;
*buffer++ = (a | r | g | b);
}
}
static FASTCALL void
fbFetch_x4b4g4r4(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD16 *pixel = (const CARD16 *) bits + x;
const CARD16 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b;
b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4;
g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16;
*buffer++ = (0xff000000 | r | g | b);
}
}
static FASTCALL void
fbFetch_a8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + x;
const CARD8 *end = pixel + width;
while (pixel < end) {
*buffer++ = (*pixel++) << 24;
}
}
static FASTCALL void
fbFetch_r3g3b2(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + x;
const CARD8 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b;
r = ((p & 0xe0) | ((p & 0xe0) >> 3) | ((p & 0xc0) >> 6)) << 16;
g = ((p & 0x1c) | ((p & 0x18) >> 3) | ((p & 0x1c) << 3)) << 8;
b = (((p & 0x03)) |
((p & 0x03) << 2) | ((p & 0x03) << 4) | ((p & 0x03) << 6));
*buffer++ = (0xff000000 | r | g | b);
}
}
static FASTCALL void
fbFetch_b2g3r3(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + x;
const CARD8 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 r, g, b;
b = (((p & 0xc0)) |
((p & 0xc0) >> 2) | ((p & 0xc0) >> 4) | ((p & 0xc0) >> 6));
g = ((p & 0x38) | ((p & 0x38) >> 3) | ((p & 0x30) << 2)) << 8;
r = (((p & 0x07)) | ((p & 0x07) << 3) | ((p & 0x06) << 6)) << 16;
*buffer++ = (0xff000000 | r | g | b);
}
}
static FASTCALL void
fbFetch_a2r2g2b2(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + x;
const CARD8 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 a, r, g, b;
a = ((p & 0xc0) * 0x55) << 18;
r = ((p & 0x30) * 0x55) << 12;
g = ((p & 0x0c) * 0x55) << 6;
b = ((p & 0x03) * 0x55);
*buffer++ = a | r | g | b;
}
}
static FASTCALL void
fbFetch_a2b2g2r2(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + x;
const CARD8 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
CARD32 a, r, g, b;
a = ((p & 0xc0) * 0x55) << 18;
b = ((p & 0x30) * 0x55) >> 6;
g = ((p & 0x0c) * 0x55) << 6;
r = ((p & 0x03) * 0x55) << 16;
*buffer++ = a | r | g | b;
}
}
static FASTCALL void
fbFetch_c8(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + x;
const CARD8 *end = pixel + width;
while (pixel < end) {
CARD32 p = *pixel++;
*buffer++ = indexed->rgba[p];
}
}
static FASTCALL void
fbFetch_x4a4(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
const CARD8 *pixel = (const CARD8 *) bits + x;
const CARD8 *end = pixel + width;
while (pixel < end) {
CARD8 p = (*pixel++) & 0xf;
*buffer++ = (p | (p << 4)) << 24;
}
}
#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 2])
#if IMAGE_BYTE_ORDER == MSBFirst
#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4)
#else
#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf)
#endif
static FASTCALL void
fbFetch_a4(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = Fetch4(bits, i + x);
p |= p << 4;
*buffer++ = p << 24;
}
}
static FASTCALL void
fbFetch_r1g2b1(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = Fetch4(bits, i + x);
CARD32 r, g, b;
r = ((p & 0x8) * 0xff) << 13;
g = ((p & 0x6) * 0x55) << 7;
b = ((p & 0x1) * 0xff);
*buffer++ = 0xff000000 | r | g | b;
}
}
static FASTCALL void
fbFetch_b1g2r1(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = Fetch4(bits, i + x);
CARD32 r, g, b;
b = ((p & 0x8) * 0xff) >> 3;
g = ((p & 0x6) * 0x55) << 7;
r = ((p & 0x1) * 0xff) << 16;
*buffer++ = 0xff000000 | r | g | b;
}
}
static FASTCALL void
fbFetch_a1r1g1b1(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = Fetch4(bits, i + x);
CARD32 a, r, g, b;
a = ((p & 0x8) * 0xff) << 21;
r = ((p & 0x4) * 0xff) << 14;
g = ((p & 0x2) * 0xff) << 7;
b = ((p & 0x1) * 0xff);
*buffer++ = a | r | g | b;
}
}
static FASTCALL void
fbFetch_a1b1g1r1(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = Fetch4(bits, i + x);
CARD32 a, r, g, b;
a = ((p & 0x8) * 0xff) << 21;
r = ((p & 0x4) * 0xff) >> 3;
g = ((p & 0x2) * 0xff) << 7;
b = ((p & 0x1) * 0xff) << 16;
*buffer++ = a | r | g | b;
}
}
static FASTCALL void
fbFetch_c4(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = Fetch4(bits, i + x);
*buffer++ = indexed->rgba[p];
}
}
static FASTCALL void
fbFetch_a1(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = ((CARD32 *) bits)[(i + x) >> 5];
CARD32 a;
#if BITMAP_BIT_ORDER == MSBFirst
a = p >> (0x1f - ((i + x) & 0x1f));
#else
a = p >> ((i + x) & 0x1f);
#endif
a = a & 1;
a |= a << 1;
a |= a << 2;
a |= a << 4;
*buffer++ = a << 24;
}
}
static FASTCALL void
fbFetch_g1(const FbBits * bits, int x, int width, CARD32 *buffer,
miIndexedPtr indexed)
{
int i;
for (i = 0; i < width; ++i) {
CARD32 p = ((CARD32 *) bits)[(i + x) >> 5];
CARD32 a;
#if BITMAP_BIT_ORDER == MSBFirst
a = p >> (0x1f - ((i + x) & 0x1f));
#else
a = p >> ((i + x) & 0x1f);
#endif
a = a & 1;
*buffer++ = indexed->rgba[a];
}
}
static fetchProc
fetchProcForPicture(PicturePtr pict)
{
switch (pict->format) {
case PICT_a8r8g8b8:
return fbFetch_a8r8g8b8;
case PICT_x8r8g8b8:
return fbFetch_x8r8g8b8;
case PICT_a8b8g8r8:
return fbFetch_a8b8g8r8;
case PICT_x8b8g8r8:
return fbFetch_x8b8g8r8;
/* 24bpp formats */
case PICT_r8g8b8:
return fbFetch_r8g8b8;
case PICT_b8g8r8:
return fbFetch_b8g8r8;
/* 16bpp formats */
case PICT_r5g6b5:
return fbFetch_r5g6b5;
case PICT_b5g6r5:
return fbFetch_b5g6r5;
case PICT_a1r5g5b5:
return fbFetch_a1r5g5b5;
case PICT_x1r5g5b5:
return fbFetch_x1r5g5b5;
case PICT_a1b5g5r5:
return fbFetch_a1b5g5r5;
case PICT_x1b5g5r5:
return fbFetch_x1b5g5r5;
case PICT_a4r4g4b4:
return fbFetch_a4r4g4b4;
case PICT_x4r4g4b4:
return fbFetch_x4r4g4b4;
case PICT_a4b4g4r4:
return fbFetch_a4b4g4r4;
case PICT_x4b4g4r4:
return fbFetch_x4b4g4r4;
/* 8bpp formats */
case PICT_a8:
return fbFetch_a8;
case PICT_r3g3b2:
return fbFetch_r3g3b2;
case PICT_b2g3r3:
return fbFetch_b2g3r3;
case PICT_a2r2g2b2:
return fbFetch_a2r2g2b2;
case PICT_a2b2g2r2:
return fbFetch_a2b2g2r2;
case PICT_c8:
return fbFetch_c8;
case PICT_g8:
return fbFetch_c8;
case PICT_x4a4:
return fbFetch_x4a4;
/* 4bpp formats */
case PICT_a4:
return fbFetch_a4;
case PICT_r1g2b1:
return fbFetch_r1g2b1;
case PICT_b1g2r1:
return fbFetch_b1g2r1;
case PICT_a1r1g1b1:
return fbFetch_a1r1g1b1;
case PICT_a1b1g1r1:
return fbFetch_a1b1g1r1;
case PICT_c4:
return fbFetch_c4;
case PICT_g4:
return fbFetch_c4;
/* 1bpp formats */
case PICT_a1:
return fbFetch_a1;
case PICT_g1:
return fbFetch_g1;
}
return NULL;
}
/*
* Pixel wise fetching
*/
typedef FASTCALL CARD32 (*fetchPixelProc) (const FbBits * bits, int offset,
miIndexedPtr indexed);
static FASTCALL CARD32
fbFetchPixel_a8r8g8b8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
return ((CARD32 *) bits)[offset];
}
static FASTCALL CARD32
fbFetchPixel_x8r8g8b8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
return ((CARD32 *) bits)[offset] | 0xff000000;
}
static FASTCALL CARD32
fbFetchPixel_a8b8g8r8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD32 *) bits)[offset];
return ((pixel & 0xff000000) |
((pixel >> 16) & 0xff) |
(pixel & 0x0000ff00) | ((pixel & 0xff) << 16));
}
static FASTCALL CARD32
fbFetchPixel_x8b8g8r8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD32 *) bits)[offset];
return ((0xff000000) |
((pixel >> 16) & 0xff) |
(pixel & 0x0000ff00) | ((pixel & 0xff) << 16));
}
static FASTCALL CARD32
fbFetchPixel_r8g8b8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD8 *pixel = ((CARD8 *) bits) + (offset * 3);
#if IMAGE_BYTE_ORDER == MSBFirst
return (0xff000000 | (pixel[0] << 16) | (pixel[1] << 8) | (pixel[2]));
#else
return (0xff000000 | (pixel[2] << 16) | (pixel[1] << 8) | (pixel[0]));
#endif
}
static FASTCALL CARD32
fbFetchPixel_b8g8r8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD8 *pixel = ((CARD8 *) bits) + (offset * 3);
#if IMAGE_BYTE_ORDER == MSBFirst
return (0xff000000 | (pixel[2] << 16) | (pixel[1] << 8) | (pixel[0]));
#else
return (0xff000000 | (pixel[0] << 16) | (pixel[1] << 8) | (pixel[2]));
#endif
}
static FASTCALL CARD32
fbFetchPixel_r5g6b5(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 r, g, b;
r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8;
g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5;
b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_b5g6r5(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 r, g, b;
b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8;
g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5;
r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_a1r5g5b5(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 a, r, g, b;
a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24;
r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9;
g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
return (a | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_x1r5g5b5(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 r, g, b;
r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9;
g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_a1b5g5r5(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 a, r, g, b;
a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24;
b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7;
g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
return (a | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_x1b5g5r5(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 r, g, b;
b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7;
g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_a4r4g4b4(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 a, r, g, b;
a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16;
r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
return (a | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_x4r4g4b4(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 r, g, b;
r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_a4b4g4r4(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 a, r, g, b;
a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16;
b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4;
g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16;
return (a | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_x4b4g4r4(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD16 *) bits)[offset];
CARD32 r, g, b;
b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4;
g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16;
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_a8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD8 *) bits)[offset];
return pixel << 24;
}
static FASTCALL CARD32
fbFetchPixel_r3g3b2(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD8 *) bits)[offset];
CARD32 r, g, b;
r = ((pixel & 0xe0) | ((pixel & 0xe0) >> 3) | ((pixel & 0xc0) >> 6)) << 16;
g = ((pixel & 0x1c) | ((pixel & 0x18) >> 3) | ((pixel & 0x1c) << 3)) << 8;
b = (((pixel & 0x03)) |
((pixel & 0x03) << 2) | ((pixel & 0x03) << 4) | ((pixel & 0x03) << 6));
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_b2g3r3(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD8 *) bits)[offset];
CARD32 r, g, b;
b = (((pixel & 0xc0)) |
((pixel & 0xc0) >> 2) | ((pixel & 0xc0) >> 4) | ((pixel & 0xc0) >> 6));
g = ((pixel & 0x38) | ((pixel & 0x38) >> 3) | ((pixel & 0x30) << 2)) << 8;
r = (((pixel & 0x07)) |
((pixel & 0x07) << 3) | ((pixel & 0x06) << 6)) << 16;
return (0xff000000 | r | g | b);
}
static FASTCALL CARD32
fbFetchPixel_a2r2g2b2(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD8 *) bits)[offset];
CARD32 a, r, g, b;
a = ((pixel & 0xc0) * 0x55) << 18;
r = ((pixel & 0x30) * 0x55) << 12;
g = ((pixel & 0x0c) * 0x55) << 6;
b = ((pixel & 0x03) * 0x55);
return a | r | g | b;
}
static FASTCALL CARD32
fbFetchPixel_a2b2g2r2(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD8 *) bits)[offset];
CARD32 a, r, g, b;
a = ((pixel & 0xc0) * 0x55) << 18;
b = ((pixel & 0x30) * 0x55) >> 6;
g = ((pixel & 0x0c) * 0x55) << 6;
r = ((pixel & 0x03) * 0x55) << 16;
return a | r | g | b;
}
static FASTCALL CARD32
fbFetchPixel_c8(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD8 *) bits)[offset];
return indexed->rgba[pixel];
}
static FASTCALL CARD32
fbFetchPixel_x4a4(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD8 *) bits)[offset];
return ((pixel & 0xf) | ((pixel & 0xf) << 4)) << 24;
}
#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 2])
#if IMAGE_BYTE_ORDER == MSBFirst
#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4)
#else
#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf)
#endif
static FASTCALL CARD32
fbFetchPixel_a4(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = Fetch4(bits, offset);
pixel |= pixel << 4;
return pixel << 24;
}
static FASTCALL CARD32
fbFetchPixel_r1g2b1(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = Fetch4(bits, offset);
CARD32 r, g, b;
r = ((pixel & 0x8) * 0xff) << 13;
g = ((pixel & 0x6) * 0x55) << 7;
b = ((pixel & 0x1) * 0xff);
return 0xff000000 | r | g | b;
}
static FASTCALL CARD32
fbFetchPixel_b1g2r1(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = Fetch4(bits, offset);
CARD32 r, g, b;
b = ((pixel & 0x8) * 0xff) >> 3;
g = ((pixel & 0x6) * 0x55) << 7;
r = ((pixel & 0x1) * 0xff) << 16;
return 0xff000000 | r | g | b;
}
static FASTCALL CARD32
fbFetchPixel_a1r1g1b1(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = Fetch4(bits, offset);
CARD32 a, r, g, b;
a = ((pixel & 0x8) * 0xff) << 21;
r = ((pixel & 0x4) * 0xff) << 14;
g = ((pixel & 0x2) * 0xff) << 7;
b = ((pixel & 0x1) * 0xff);
return a | r | g | b;
}
static FASTCALL CARD32
fbFetchPixel_a1b1g1r1(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = Fetch4(bits, offset);
CARD32 a, r, g, b;
a = ((pixel & 0x8) * 0xff) << 21;
r = ((pixel & 0x4) * 0xff) >> 3;
g = ((pixel & 0x2) * 0xff) << 7;
b = ((pixel & 0x1) * 0xff) << 16;
return a | r | g | b;
}
static FASTCALL CARD32
fbFetchPixel_c4(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = Fetch4(bits, offset);
return indexed->rgba[pixel];
}
static FASTCALL CARD32
fbFetchPixel_a1(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD32 *) bits)[offset >> 5];
CARD32 a;
#if BITMAP_BIT_ORDER == MSBFirst
a = pixel >> (0x1f - (offset & 0x1f));
#else
a = pixel >> (offset & 0x1f);
#endif
a = a & 1;
a |= a << 1;
a |= a << 2;
a |= a << 4;
return a << 24;
}
static FASTCALL CARD32
fbFetchPixel_g1(const FbBits * bits, int offset, miIndexedPtr indexed)
{
CARD32 pixel = ((CARD32 *) bits)[offset >> 5];
CARD32 a;
#if BITMAP_BIT_ORDER == MSBFirst
a = pixel >> (0x1f - (offset & 0x1f));
#else
a = pixel >> (offset & 0x1f);
#endif
a = a & 1;
return indexed->rgba[a];
}
static fetchPixelProc
fetchPixelProcForPicture(PicturePtr pict)
{
switch (pict->format) {
case PICT_a8r8g8b8:
return fbFetchPixel_a8r8g8b8;
case PICT_x8r8g8b8:
return fbFetchPixel_x8r8g8b8;
case PICT_a8b8g8r8:
return fbFetchPixel_a8b8g8r8;
case PICT_x8b8g8r8:
return fbFetchPixel_x8b8g8r8;
/* 24bpp formats */
case PICT_r8g8b8:
return fbFetchPixel_r8g8b8;