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.
209 lines
7.3 KiB
209 lines
7.3 KiB
/**************************************************************************
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
*
|
|
* Module Name:
|
|
*
|
|
* CPU-specific scan operations
|
|
*
|
|
* Abstract:
|
|
*
|
|
* Handles scan operations which only work on certain CPU's.
|
|
* Currently only used by EpAlphaBlender. This works by overwriting the
|
|
* function pointer arrays with ones holding CPU-specific information.
|
|
*
|
|
* Created:
|
|
*
|
|
* 05/30/2000 agodfrey
|
|
* Created it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#include "precomp.hpp"
|
|
|
|
#include "scanoperationinternal.hpp"
|
|
|
|
using namespace ScanOperation;
|
|
|
|
// This variable records whether Initialize() has been called yet.
|
|
|
|
BOOL CPUSpecificOps::Initialized = FALSE;
|
|
|
|
/**************************************************************************\
|
|
*
|
|
* Special-case low-quality blend operations which blend directly to a
|
|
* given destination format (with the source in 32BPP_PARGB).
|
|
*
|
|
* Some of these operations may use MMX instructions.
|
|
*
|
|
* Notes:
|
|
*
|
|
* The 555/565 cases support both dithering and non-dithering, via the flag
|
|
* OtherParams::DoingDither.
|
|
*
|
|
* We leave out PIXFMT_32BPP_ARGB and PIXFMT_64BPP_ARGB, since they're not
|
|
* "ignore alpha" formats, so we'd need to AlphaDivide after the blend.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
static ScanOpFunc BlendOpsLowQuality_MMX[PIXFMT_MAX] =
|
|
{
|
|
NULL, // PIXFMT_UNDEFINED
|
|
NULL, // PIXFMT_1BPP_INDEXED
|
|
NULL, // PIXFMT_4BPP_INDEXED
|
|
NULL, // PIXFMT_8BPP_INDEXED
|
|
NULL, // PIXFMT_16BPP_GRAYSCALE
|
|
Dither_Blend_sRGB_555_MMX, // PIXFMT_16BPP_RGB555
|
|
Dither_Blend_sRGB_565_MMX, // PIXFMT_16BPP_RGB565
|
|
NULL, // PIXFMT_16BPP_ARGB1555
|
|
Blend_sRGB_24, // PIXFMT_24BPP_RGB
|
|
Blend_sRGB_sRGB_MMX, // PIXFMT_32BPP_RGB
|
|
NULL, // PIXFMT_32BPP_ARGB
|
|
Blend_sRGB_sRGB_MMX, // PIXFMT_32BPP_PARGB
|
|
NULL, // PIXFMT_48BPP_RGB
|
|
NULL, // PIXFMT_64BPP_ARGB
|
|
NULL, // PIXFMT_64BPP_PARGB
|
|
Blend_sRGB_24BGR // PIXFMT_24BPP_BGR
|
|
};
|
|
|
|
/**************************************************************************\
|
|
*
|
|
* Special-case gamma-corrected blend operations which blend directly to a
|
|
* given destination format (with the source in 32BPP_PARGB).
|
|
*
|
|
* Some of these operations may use MMX instructions.
|
|
*
|
|
* Notes:
|
|
*
|
|
* We leave out PIXFMT_32BPP_ARGB and PIXFMT_64BPP_ARGB, since they're not
|
|
* "ignore alpha" formats, so we'd need to AlphaDivide after the blend.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
static ScanOpFunc BlendOpsHighQuality_MMX[PIXFMT_MAX] =
|
|
{
|
|
NULL, // PIXFMT_UNDEFINED
|
|
NULL, // PIXFMT_1BPP_INDEXED
|
|
NULL, // PIXFMT_4BPP_INDEXED
|
|
NULL, // PIXFMT_8BPP_INDEXED
|
|
NULL, // PIXFMT_16BPP_GRAYSCALE
|
|
BlendLinear_sRGB_555_MMX, // PIXFMT_16BPP_RGB555
|
|
BlendLinear_sRGB_565_MMX, // PIXFMT_16BPP_RGB565
|
|
NULL, // PIXFMT_16BPP_ARGB1555
|
|
NULL, // PIXFMT_24BPP_RGB
|
|
BlendLinear_sRGB_32RGB_MMX, // PIXFMT_32BPP_RGB
|
|
NULL, // PIXFMT_32BPP_ARGB
|
|
NULL, // PIXFMT_32BPP_PARGB
|
|
NULL, // PIXFMT_48BPP_RGB
|
|
NULL, // PIXFMT_64BPP_ARGB
|
|
Blend_sRGB64_sRGB64_MMX, // PIXFMT_64BPP_PARGB
|
|
NULL // PIXFMT_24BPP_BGR
|
|
};
|
|
|
|
/**************************************************************************\
|
|
*
|
|
* Operations which convert from the closest canonical format - either
|
|
* 32BPP_ARGB or 64BPP_ARGB).
|
|
*
|
|
* This is specific to EpAlphaBlender. EpFormatConverter uses a different
|
|
* table; some of the entries are different.
|
|
*
|
|
* The NULL entries for 32BPP_ARGB and 64_BPP_ARGB are used to indicate that no
|
|
* conversion is necessary.
|
|
*
|
|
* Some of these operations use MMX instructions.
|
|
*
|
|
* Notes:
|
|
*
|
|
* The 555/565 cases support both dithering and non-dithering, via the flag
|
|
* OtherParams::DoingDither.
|
|
*
|
|
* For 8bpp, we use the 16-color halftoning function. Initialize() will
|
|
* need to work out if it can use something better, like the 216-color
|
|
* halftone function. We should really have a 'nearest-color-matching' function
|
|
* here, to support drawing to bitmaps with arbitrary palettes (the "16 VGA
|
|
* colors" assumption is only true for the screen.)
|
|
*
|
|
\**************************************************************************/
|
|
|
|
static ScanOpFunc ABConvertFromCanonicalOps_MMX[PIXFMT_MAX] =
|
|
{
|
|
NULL, // PIXFMT_UNDEFINED
|
|
NULL, // PIXFMT_1BPP_INDEXED
|
|
NULL, // PIXFMT_4BPP_INDEXED
|
|
HalftoneToScreen_sRGB_8_16, // PIXFMT_8BPP_INDEXED
|
|
NULL, // PIXFMT_16BPP_GRAYSCALE
|
|
Dither_sRGB_555_MMX, // PIXFMT_16BPP_RGB555
|
|
Dither_sRGB_565_MMX, // PIXFMT_16BPP_RGB565
|
|
Quantize_sRGB_1555, // PIXFMT_16BPP_ARGB1555
|
|
Quantize_sRGB_24, // PIXFMT_24BPP_RGB
|
|
Quantize_sRGB_32RGB, // PIXFMT_32BPP_RGB
|
|
NULL, // PIXFMT_32BPP_ARGB
|
|
AlphaMultiply_sRGB, // PIXFMT_32BPP_PARGB
|
|
Quantize_sRGB64_48, // PIXFMT_48BPP_RGB
|
|
NULL, // PIXFMT_64BPP_ARGB
|
|
AlphaMultiply_sRGB64, // PIXFMT_64BPP_PARGB
|
|
Quantize_sRGB_24BGR // PIXFMT_24BPP_BGR
|
|
};
|
|
|
|
/**************************************************************************
|
|
*
|
|
* Function Description:
|
|
*
|
|
* Initializes the function pointer arrays with processor-specific
|
|
* data. Should only be called once.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* NONE
|
|
*
|
|
* Created:
|
|
*
|
|
* 05/30/2000 agodfrey
|
|
* Created it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
VOID
|
|
CPUSpecificOps::Initialize()
|
|
{
|
|
// Thread-protect the access to the global "Initialized" and
|
|
// the function pointer arrays. Beware: Users of these tables (currently
|
|
// only EpAlphaBlender::Initialize()) must be careful when they read those
|
|
// arrays. They must either protect the access under this critical section,
|
|
// or simply ensure that they've called this function first.
|
|
|
|
LoadLibraryCriticalSection llcs; // Hey, it's an 'initialization' critsec!
|
|
|
|
// Make sure no-one calls us before OSInfo::HasMMX is initialized
|
|
|
|
#if DBG
|
|
|
|
static BOOL noMMX = FALSE;
|
|
ASSERT(!(noMMX && OSInfo::HasMMX));
|
|
if (!OSInfo::HasMMX)
|
|
{
|
|
noMMX = TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!Initialized)
|
|
{
|
|
INT i;
|
|
|
|
if (OSInfo::HasMMX)
|
|
{
|
|
for (i=0; i<PIXFMT_MAX; i++)
|
|
{
|
|
BlendOpsLowQuality[i] = BlendOpsLowQuality_MMX[i];
|
|
BlendOpsHighQuality[i] = BlendOpsHighQuality_MMX[i];
|
|
ABConvertFromCanonicalOps[i] = ABConvertFromCanonicalOps_MMX[i];
|
|
}
|
|
}
|
|
|
|
Initialized = TRUE;
|
|
}
|
|
}
|
|
|
|
|