/************************************************************************** * * 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