Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

399 lines
12 KiB

/**************************************************************************\
*
* Copyright (c) 2000 Microsoft Corporation
*
* Module name:
*
* The "Dither" scan operation.
*
* Abstract:
*
* See Gdiplus\Specs\ScanOperation.doc for an overview.
*
* Notes:
*
* Revision History:
*
* 01/19/2000 andrewgo
* Created it.
*
\**************************************************************************/
#include "precomp.hpp"
/**************************************************************************\
*
* Operation Description:
*
* Dither: Dither from 32bpp ARGB to 16bpp.
*
* Arguments:
*
* dst - The destination scan
* src - The source scan (32bpp ARGB)
* count - The length of the scan, in pixels
* otherParams - Additional data. (We use X and Y.)
*
* Return Value:
*
* None
*
* Notes:
*
* Special cases which alpha-blend and dither in one step, should probably
* go in this file, but be named e.g. Blend_sRGB_565_Dithered.
*
* History:
*
* 01/19/2000 andrewgo
* Created it.
* 01/19/2000 agodfrey
* Stashed it here for the time being.
*
\**************************************************************************/
UINT32 Saturate5Bit[] = { 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
31 };
UINT32 Saturate6Bit[] = { 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
63 };
UINT32 Dither5BitR[16] = { 0x00000000, 0x00040000, 0x00010000, 0x00050000,
0x00060000, 0x00020000, 0x00070000, 0x00030000,
0x00010000, 0x00050000, 0x00000000, 0x00040000,
0x00070000, 0x00030000, 0x00060000, 0x00020000 };
UINT32 Dither5BitG[16] = { 0x00000000, 0x00000400, 0x00000100, 0x00000500,
0x00000600, 0x00000200, 0x00000700, 0x00000300,
0x00000100, 0x00000500, 0x00000000, 0x00000400,
0x00000700, 0x00000300, 0x00000600, 0x00000200 };
UINT32 Dither6BitG[16] = { 0x00000000, 0x00000200, 0x00000000, 0x00000200,
0x00000300, 0x00000100, 0x00000300, 0x00000100,
0x00000000, 0x00000200, 0x00000000, 0x00000200,
0x00000300, 0x00000100, 0x00000300, 0x00000100 };
UINT32 Dither5BitB[16] = { 0x00000000, 0x00000004, 0x00000001, 0x00000005,
0x00000006, 0x00000002, 0x00000007, 0x00000003,
0x00000001, 0x00000005, 0x00000000, 0x00000004,
0x00000007, 0x00000003, 0x00000006, 0x00000002 };
// The following 'Dither565' and 'Dither555' matrices are 4 by 4
// arrays for adding straight to an ARGB dword value. Every row
// is repeated to allow us to do 128-bit reads with wrapping.
UINT32 Dither565[32] = { 0x00000000, 0x00040204, 0x00010001, 0x00050205,
0x00000000, 0x00040204, 0x00010001, 0x00050205,
0x00060306, 0x00020102, 0x00070307, 0x00030103,
0x00060306, 0x00020102, 0x00070307, 0x00030103,
0x00010001, 0x00050205, 0x00000000, 0x00040204,
0x00010001, 0x00050205, 0x00000000, 0x00040204,
0x00070307, 0x00030103, 0x00060306, 0x00020102,
0x00070307, 0x00030103, 0x00060306, 0x00020102 };
UINT32 Dither555[32] = { 0x00000000, 0x00040404, 0x00010101, 0x00050505,
0x00000000, 0x00040404, 0x00010101, 0x00050505,
0x00060606, 0x00020202, 0x00070707, 0x00030303,
0x00060606, 0x00020202, 0x00070707, 0x00030303,
0x00010101, 0x00050505, 0x00000000, 0x00040404,
0x00010101, 0x00050505, 0x00000000, 0x00040404,
0x00070707, 0x00030303, 0x00060606, 0x00020202,
0x00070707, 0x00030303, 0x00060606, 0x00020202 };
// The 'DitherNone' matrix allows us to disable dithering in a dithering
// routine:
UINT32 DitherNone[4] = { 0, 0, 0, 0 };
// Dither to 16bpp 565
VOID FASTCALL
ScanOperation::Dither_sRGB_565(
VOID *dst,
const VOID *src,
INT count,
const OtherParams *otherParams
)
{
// Since the MMX versions easily handle both dithering and non-dithering,
// it makes it simpler if all the 16bpp functions handle both.
if (!otherParams->DoingDither)
{
Quantize_sRGB_565(dst, src, count, otherParams);
return;
}
DEFINE_POINTERS(ARGB, WORD);
ASSERT(count != 0);
ASSERT(otherParams);
INT x = otherParams->X;
INT y = otherParams->Y;
// !!![andrewgo] Are we getting the window-relative (x, y)? (Don't think so!)
INT startDitherIndex = (y & 3) * 4;
do {
UINT32 src = *s;
x = (x & 3) + startDitherIndex;
*d = (WORD)
(Saturate5Bit[((src & 0xff0000) + Dither5BitR[x]) >> 19] << 11) +
(Saturate6Bit[((src & 0x00ff00) + Dither6BitG[x]) >> 10] << 5) +
(Saturate5Bit[((src & 0x0000ff) + Dither5BitB[x]) >> 3]);
s++;
d++;
x++;
} while (--count != 0);
}
// Dither to 16bpp 555
VOID FASTCALL
ScanOperation::Dither_sRGB_555(
VOID *dst,
const VOID *src,
INT count,
const OtherParams *otherParams
)
{
// Since the MMX versions easily handle both dithering and non-dithering,
// it makes it simpler if all the 16bpp functions handle both.
if (!otherParams->DoingDither)
{
Quantize_sRGB_555(dst, src, count, otherParams);
return;
}
DEFINE_POINTERS(ARGB, WORD);
ASSERT(count != 0);
ASSERT(otherParams);
INT x = otherParams->X;
INT y = otherParams->Y;
INT startDitherIndex = (y & 3) * 4;
do {
UINT32 src = *s;
x = (x & 3) + startDitherIndex;
*d = (WORD)
(Saturate5Bit[((src & 0xff0000) + Dither5BitR[x]) >> 19] << 10) +
(Saturate5Bit[((src & 0x00ff00) + Dither5BitG[x]) >> 11] << 5) +
(Saturate5Bit[((src & 0x0000ff) + Dither5BitB[x]) >> 3]);
s++;
d++;
x++;
} while (--count != 0);
}
// Blend from sRGB to 16bpp 565, with dithering.
VOID FASTCALL
ScanOperation::Dither_Blend_sRGB_565(
VOID *dst,
const VOID *src,
INT count,
const OtherParams *otherParams
)
{
// Since the MMX versions easily handle both dithering and non-dithering,
// it makes it simpler if all the 16bpp functions handle both.
if (!otherParams->DoingDither)
{
Blend_sRGB_565(dst, src, count, otherParams);
return;
}
DEFINE_POINTERS(UINT16, UINT16)
DEFINE_BLEND_POINTER(ARGB)
ASSERT(count>0);
INT x = otherParams->X;
INT y = otherParams->Y;
INT startDitherIndex = (y & 3) * 4;
do {
UINT32 blendPixel = *bl;
UINT32 alpha = blendPixel >> 24;
x = (x & 3) + startDitherIndex;
if (alpha != 0)
{
UINT32 srcPixel;
UINT r, g, b;
r = blendPixel & 0xff0000;
g = blendPixel & 0x00ff00;
b = blendPixel & 0x0000ff;
if (alpha != 255)
{
srcPixel = *s;
UINT sr = (srcPixel >> 11) & 0x1f;
UINT sg = (srcPixel >> 5) & 0x3f;
UINT sb = (srcPixel ) & 0x1f;
sr = (sr << 3) | (sr >> 2);
sg = (sg << 2) | (sg >> 4);
sb = (sb << 3) | (sb >> 2);
//
// Dst = B + (1-Alpha) * S
//
ULONG Multa = 255 - alpha;
ULONG _D1_000000GG = sg;
ULONG _D1_00RR00BB = sb | (sr << 16);
ULONG _D2_0000GGGG = _D1_000000GG * Multa + 0x00000080;
ULONG _D2_RRRRBBBB = _D1_00RR00BB * Multa + 0x00800080;
ULONG _D3_000000GG = (_D2_0000GGGG & 0x0000ff00) >> 8;
ULONG _D3_00RR00BB = (_D2_RRRRBBBB & 0xff00ff00) >> 8;
ULONG _D4_0000GG00 = (_D2_0000GGGG + _D3_000000GG) & 0x0000FF00;
ULONG _D4_00RR00BB = ((_D2_RRRRBBBB + _D3_00RR00BB) & 0xFF00FF00) >> 8;
r += _D4_00RR00BB; // The BB part will be shifted off
g += _D4_0000GG00;
b += _D4_00RR00BB & 0x0000ff;
}
*d = (WORD)
(Saturate5Bit[(r + Dither5BitR[x]) >> 19] << 11) +
(Saturate6Bit[(g + Dither6BitG[x]) >> 10] << 5) +
(Saturate5Bit[(b + Dither5BitB[x]) >> 3]);
}
bl++;
s++;
d++;
x++;
} while (--count != 0);
}
// Blend from sRGB to 16bpp 555, with dithering.
VOID FASTCALL
ScanOperation::Dither_Blend_sRGB_555(
VOID *dst,
const VOID *src,
INT count,
const OtherParams *otherParams
)
{
// Since the MMX versions easily handle both dithering and non-dithering,
// it makes it simpler if all the 16bpp functions handle both.
if (!otherParams->DoingDither)
{
Blend_sRGB_555(dst, src, count, otherParams);
return;
}
DEFINE_POINTERS(UINT16, UINT16)
DEFINE_BLEND_POINTER(ARGB)
ASSERT(count>0);
INT x = otherParams->X;
INT y = otherParams->Y;
INT startDitherIndex = (y & 3) * 4;
do {
UINT32 blendPixel = *bl;
UINT32 alpha = blendPixel >> 24;
x = (x & 3) + startDitherIndex;
if (alpha != 0)
{
UINT32 srcPixel;
UINT r, g, b;
r = blendPixel & 0xff0000;
g = blendPixel & 0x00ff00;
b = blendPixel & 0x0000ff;
if (alpha != 255)
{
srcPixel = *s;
UINT sr = (srcPixel >> 10) & 0x1f;
UINT sg = (srcPixel >> 5) & 0x1f;
UINT sb = (srcPixel ) & 0x1f;
sr = (sr << 3) | (sr >> 2);
sg = (sg << 3) | (sg >> 2);
sb = (sb << 3) | (sb >> 2);
//
// Dst = B + (1-Alpha) * S
//
ULONG Multa = 255 - alpha;
ULONG _D1_000000GG = sg;
ULONG _D1_00RR00BB = sb | (sr << 16);
ULONG _D2_0000GGGG = _D1_000000GG * Multa + 0x00000080;
ULONG _D2_RRRRBBBB = _D1_00RR00BB * Multa + 0x00800080;
ULONG _D3_000000GG = (_D2_0000GGGG & 0x0000ff00) >> 8;
ULONG _D3_00RR00BB = (_D2_RRRRBBBB & 0xff00ff00) >> 8;
ULONG _D4_0000GG00 = (_D2_0000GGGG + _D3_000000GG) & 0x0000FF00;
ULONG _D4_00RR00BB = ((_D2_RRRRBBBB + _D3_00RR00BB) & 0xFF00FF00) >> 8;
r += _D4_00RR00BB; // The BB part will be shifted off
g += _D4_0000GG00;
b += _D4_00RR00BB & 0x0000ff;
}
*d = (WORD)
(Saturate5Bit[(r + Dither5BitR[x]) >> 19] << 10) +
(Saturate5Bit[(g + Dither5BitG[x]) >> 11] << 5) +
(Saturate5Bit[(b + Dither5BitB[x]) >> 3]);
}
bl++;
s++;
d++;
x++;
} while (--count != 0);
}
// Generate 555 versions of the routines defined in 'sodither.inc'
#define DITHER_BLEND_555 1
#include "SODither.inc"
// Generate 565 versions of the routines defined in 'sodither.inc'
#undef DITHER_BLEND_555
#define DITHER_BLEND_555 0
#include "SODither.inc"