[Webkit-unassigned] [Bug 103693] Remove conversion to/from float and float division from ImageFrame::setRGBA

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Thu Nov 29 17:43:56 PST 2012


https://bugs.webkit.org/show_bug.cgi?id=103693


Viatcheslav Ostapenko <ostap73 at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
 Attachment #176859|ImageDecoderPerf.cpp        |setRGBPerf.cpp
           filename|                            |




--- Comment #2 from Viatcheslav Ostapenko <ostap73 at gmail.com>  2012-11-29 17:46:14 PST ---
(From update of attachment 176859)
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef unsigned PixelData;

bool m_premultiplyAlpha = true;

inline void setRGBA_orig(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
    if (m_premultiplyAlpha && a < 255) {
        if (!a) {
            *dest = 0;
            return;
        }

        float alphaPercent = a / 255.0f;
        r = static_cast<unsigned>(r * alphaPercent);
        g = static_cast<unsigned>(g * alphaPercent);
        b = static_cast<unsigned>(b * alphaPercent);
    }

    *dest = (a << 24 | r << 16 | g << 8 | b);
}

const int fixPointShift = 24;
const unsigned fixPointMult = unsigned(1.0 / 255.0 * (1 << fixPointShift)) + 1;
inline void setRGBA_fixPointMult(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
    if (m_premultiplyAlpha && a < 255) {
        if (!a) {
            *dest = 0;
            return;
        }

        unsigned alphaMult = a * fixPointMult;
        r = (r * alphaMult) >> fixPointShift;
        g = (g * alphaMult) >> fixPointShift;
        b = (b * alphaMult) >> fixPointShift;
    }

    *dest = (a << 24 | r << 16 | g << 8 | b);
}

inline void setRGBA_integerDiv(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
    if (m_premultiplyAlpha && a < 255) {
        if (!a) {
            *dest = 0;
            return;
        }

        r = r * a / 255;
        g = g * a / 255;
        b = b * a / 255;
    }

    *dest = (a << 24 | r << 16 | g << 8 | b);
}

inline unsigned fastDiv255(unsigned a)
{
    return (a + (a >> 8) + 1) >> 8;
}

inline void setRGBA_fastDiv255(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
    if (m_premultiplyAlpha && a < 255) {
        if (!a) {
            *dest = 0;
            return;
        }

        r = fastDiv255(r * a);
        g = fastDiv255(g * a);
        b = fastDiv255(b * a);
    }

    *dest = (a << 24 | r << 16 | g << 8 | b);
}

const unsigned bufferSize = 256 * 1024 * 1024; // Something bigger than all cpu caches
PixelData source[bufferSize];
PixelData dest[bufferSize];

inline unsigned char* castUChar(void* p)
{
    return static_cast<unsigned char *>(p);
}

void runTests()
{
    unsigned i, tmp;
    unsigned char *bytesEnd = castUChar(&(source[bufferSize]));
    PixelData* destPosition;
    unsigned char *bytes;

    clock_t start;
    clock_t end;

    start = clock();
    for(bytes = castUChar(&(source[0])), destPosition = &dest[0]; bytes < bytesEnd; bytes += 4, destPosition++) {
        setRGBA_integerDiv(destPosition, bytes[0], bytes[1], bytes[2], bytes[3]);
    }
    end = clock();
    printf("1: %lu\t", end - start);

    start = clock();
    for(bytes = castUChar(&(source[0])), destPosition = &dest[0]; bytes < bytesEnd; bytes += 4, destPosition++) {
        setRGBA_fastDiv255(destPosition, bytes[0], bytes[1], bytes[2], bytes[3]);
    }
    end = clock();
    printf("2: %lu\t", end - start);

    start = clock();
    for(bytes = castUChar(&(source[0])), destPosition = &dest[0]; bytes < bytesEnd; bytes += 4, destPosition++) {
        setRGBA_fixPointMult(destPosition, bytes[0], bytes[1], bytes[2], bytes[3]);
    }
    end = clock();
    printf("3: %lu\t", end - start);

    start = clock();
    for(bytes = castUChar(&(source[0])), destPosition = &dest[0]; bytes < bytesEnd; bytes += 4, destPosition++) {
        setRGBA_orig(destPosition, bytes[0], bytes[1], bytes[2], bytes[3]);
    }
    end = clock();
    printf("4: %lu\n", end - start);
}

int main(int argc, char *argv[])
{
    unsigned i, j;

    unsigned diffValues = 0;
    // Fastdiv and fixedpoint mult precision check
    for(i = 0; i < 256; i++) {
        for(j = 0; j < 256; j++) {

            unsigned a = fastDiv255(i * j);

            unsigned alphaMult = i * fixPointMult;
            unsigned b = (j * alphaMult) >> fixPointShift;

            unsigned c = j * i / 255;

            float alphaPercent = i / 255.0f;
            unsigned d = static_cast<unsigned>(j * alphaPercent);
            if (a != d || b != d || c != d) {
                printf("Alpha; %u,\t color: %u,\t a: %u,\t b: %u,\t c: %u,\t d: %u\n", i, j, a, b, c, d);
                diffValues++;
            }
        }
    }
    printf("Different %u values\n", diffValues);

    memset(&dest[0], 0, sizeof(dest));
    do { // Run benchmarks with both values of m_premultiplyAlpha to make sure it is not optimized out
        printf("Premultiply Alpha: %d\n",m_premultiplyAlpha);

        printf("All 0 buffer:\n");
        memset(&source[0], 0, sizeof(source));
        runTests();

        printf("All 255 buffer:\n");
        memset(&source[0], 255, sizeof(source));
        runTests();

        printf("Pseudo random buffer:\n");
        // Fill buffer with 25% 0 alpha, 25% 255 alpha and other random values
        for(i = 0; i < bufferSize; i += 4) {
            source[i] = PixelData(rand()) & 0xFFFFFF;
            source[i] = PixelData(rand());
            source[i] = PixelData(rand()) | 0xFF000000;
            source[i] = PixelData(rand());
        }
        runTests();

        m_premultiplyAlpha = 1 - m_premultiplyAlpha;
    } while(m_premultiplyAlpha == false);
}

-- 
Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.


More information about the webkit-unassigned mailing list