C++程序  |  507行  |  13.61 KB

/* libs/graphics/sgl/SkGraphics.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

#include "SkGraphics.h"

#include "Sk64.h"
#include "SkBlitter.h"
#include "SkCanvas.h"
#include "SkFloat.h"
#include "SkGeometry.h"
#include "SkGlobals.h"
#include "SkMath.h"
#include "SkMatrix.h"
#include "SkPath.h"
#include "SkPathEffect.h"
#include "SkRandom.h"
#include "SkRefCnt.h"
#include "SkScalerContext.h"
#include "SkShader.h"
#include "SkStream.h"
#include "SkTSearch.h"
#include "SkTime.h"
#include "SkUtils.h"
#include "SkXfermode.h"

#if 0

#define SK_SORT_TEMPLATE_TYPE       int
#define SK_SORT_TEMPLATE_NAME       sort_int
#define SK_SORT_TEMPLATE_CMP(a, b)   ((a) - (b))
#include "SkSortTemplate.h"

#define SK_SORT_TEMPLATE_TYPE       int*
#define SK_SORT_TEMPLATE_NAME       sort_intptr
#define SK_SORT_TEMPLATE_CMP(a, b)   (*(a) - *(b))
#include "SkSortTemplate.h"

static void test_sort()
{
    int array[] = { 4, 3, 7, 5, 2, 5, 1, 2, 9, 6, 7, 4, 5, 3, 1, 0 };
    int* ptr[SK_ARRAY_COUNT(array)];
    int i, N = SK_ARRAY_COUNT(array) - 1;

    for (i = 0; i < N; i++)
        printf(" %d", array[i]);
    printf("\n");
    
    for (i = 0; i < N; i++)
        ptr[i] = &array[i];
    sort_intptr(ptr, N);
    for (i = 0; i < N; i++)
        printf(" %d", *ptr[i]);
    printf("\n");

    sort_int(array, N);
    for (i = 0; i < N; i++)
        printf(" %d", array[i]);
    printf("\n");

}
#endif

#define SPEED_TESTx

#define typesizeline(type)  { #type , sizeof(type) }


#ifdef BUILD_EMBOSS_TABLE
    extern void SkEmbossMask_BuildTable();
#endif

#ifdef BUILD_RADIALGRADIENT_TABLE
    extern void SkRadialGradient_BuildTable();
#endif

#define BIG_LOOP_COUNT  1000000
#define TEXT_LOOP_COUNT 1000

#ifdef SPEED_TEST
static int test_s64(int i)
{
    Sk64    a, b, c;
    
    c.set(0);
    a.set(i);
    b.setMul(i, i);
    a.add(b);
    a.add(c);
    return c.getFixed();
}

static int test_native_64(int i)
{
    int16_t    a, b, c;
    
    c = 0;
    a = i;
    b = (int64_t)i * i;
    a += b;
    a += c;
    return (int)(c >> 16);
}

static void test_drawText(SkBitmap::Config config, SkColor color)
{
    SkBitmap    bm;
    
    bm.setConfig(config, 320, 240);
    bm.allocPixels();
    
    SkCanvas canvas(bm);
    SkPaint  paint;
    
    paint.setAntiAlias(true);
    paint.setTextSize(SkIntToScalar(12));
    paint.setColor(color);
    
    SkScalar x = SkIntToScalar(20);
    SkScalar y = SkIntToScalar(100);
    const char* text = "Hamburgefons";
    size_t      len = strlen(text);

    // draw once to populate the cache
    canvas.drawText(text, len, x, y, paint);
    
    SkMSec now = SkTime::GetMSecs();
    for (int i = 0; i < TEXT_LOOP_COUNT; i++)
        canvas.drawText(text, len, x, y, paint);
    printf("----------- Config: %d, Color=%x, CPS = %g\n", config, color,
           len * TEXT_LOOP_COUNT * 1000.0 / (SkTime::GetMSecs() - now));
}

#endif

#ifdef SK_CAN_USE_FLOAT
#include "SkFloatBits.h"

static inline float fast_inc(float x) {
    SkFloatIntUnion data;
    data.fFloat = x;
    data.fSignBitInt += 1;
    return data.fFloat;
}

extern float dummy();
int time_math() {
    SkMSec now;
    int i;
    int sum = 0;
    const int repeat = 1000000;
    float f;

    f = dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += (int)f; f = fast_inc(f);
        sum += (int)f; f = fast_inc(f);
        sum += (int)f; f = fast_inc(f);
        sum += (int)f; f = fast_inc(f);
    }
    SkDebugf("---- native cast %d\n", SkTime::GetMSecs() - now);

    f = dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += SkFloatToIntCast(f); f = fast_inc(f);
        sum += SkFloatToIntCast(f); f = fast_inc(f);
        sum += SkFloatToIntCast(f); f = fast_inc(f);
        sum += SkFloatToIntCast(f); f = fast_inc(f);
    }
    SkDebugf("---- hack cast %d\n", SkTime::GetMSecs() - now);

    f = dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += (int)floorf(f + 0.5f); f = fast_inc(f);
        sum += (int)floorf(f + 0.5f); f = fast_inc(f);
        sum += (int)floorf(f + 0.5f); f = fast_inc(f);
        sum += (int)floorf(f + 0.5f); f = fast_inc(f);
    }
    SkDebugf("---- native round %d\n", SkTime::GetMSecs() - now);
    
    f = dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += SkFloatToIntRound(f); f = fast_inc(f);
        sum += SkFloatToIntRound(f); f = fast_inc(f);
        sum += SkFloatToIntRound(f); f = fast_inc(f);
        sum += SkFloatToIntRound(f); f = fast_inc(f);
    }
    SkDebugf("---- hack round %d\n", SkTime::GetMSecs() - now);
    
    f = dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
    }
    SkDebugf("---- native floor %d\n", SkTime::GetMSecs() - now);
    
    f = dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += SkFloatToIntFloor(f); f = fast_inc(f);
        sum += SkFloatToIntFloor(f); f = fast_inc(f);
        sum += SkFloatToIntFloor(f); f = fast_inc(f);
        sum += SkFloatToIntFloor(f); f = fast_inc(f);
    }
    SkDebugf("---- hack floor %d\n", SkTime::GetMSecs() - now);
    
    return sum;
}

#if 0
static float time_intToFloat() {
    const int repeat = 1000000;
    int i, n;
    SkMSec now;
    float sum = 0;
    
    n = (int)dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += (float)n; n += 1;
        sum += (float)n; n += 1;
        sum += (float)n; n += 1;
        sum += (float)n; n += 1;
    }
    SkDebugf("---- native i2f %d\n", SkTime::GetMSecs() - now);
    
    n = (int)dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += SkIntToFloatCast(n); n += 1;
        sum += SkIntToFloatCast(n); n += 1;
        sum += SkIntToFloatCast(n); n += 1;
        sum += SkIntToFloatCast(n); n += 1;
    }
    SkDebugf("---- check i2f %d\n", SkTime::GetMSecs() - now);

    n = (int)dummy();
    now = SkTime::GetMSecs();
    for (i = repeat - 1; i >= 0; --i) {
        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
    }
    SkDebugf("---- nocheck i2f %d\n", SkTime::GetMSecs() - now);

    return sum;
}
#endif
#endif

void SkGraphics::Init()
{
    SkGlobals::Init();

#ifdef SK_CAN_USE_FLOAT
//    time_math();
//    time_intToFloat();
#endif
    
#ifdef BUILD_EMBOSS_TABLE
    SkEmbossMask_BuildTable();
#endif
#ifdef BUILD_RADIALGRADIENT_TABLE
    SkRadialGradient_BuildTable();
#endif

#ifdef SK_DEBUGx
    int i;

    static const struct {
        const char* fTypeName;
        size_t      fSizeOf;
    } gTypeSize[] = {
        typesizeline(char),
        typesizeline(short),
        typesizeline(int),
        typesizeline(long),
        typesizeline(size_t),
        typesizeline(void*),

        typesizeline(S8CPU),
        typesizeline(U8CPU),
        typesizeline(S16CPU),
        typesizeline(U16CPU),

        typesizeline(SkPoint),
        typesizeline(SkRect),
        typesizeline(SkMatrix),
        typesizeline(SkPath),
        typesizeline(SkGlyph),
        typesizeline(SkRefCnt),

        typesizeline(SkPaint),
        typesizeline(SkCanvas),
        typesizeline(SkBlitter),
        typesizeline(SkShader),
        typesizeline(SkXfermode),
        typesizeline(SkPathEffect)
    };

#ifdef SK_CPU_BENDIAN
    SkDebugf("SkGraphics: big-endian\n");
#else
    SkDebugf("SkGraphics: little-endian\n");
#endif

    {
        char    test = 0xFF;
        int     itest = test;   // promote to int, see if it sign-extended
        if (itest < 0)
            SkDebugf("SkGraphics: char is signed\n");
        else
            SkDebugf("SkGraphics: char is unsigned\n");
    }
    for (i = 0; i < (int)SK_ARRAY_COUNT(gTypeSize); i++) {
        SkDebugf("SkGraphics: sizeof(%s) = %d\n",
                 gTypeSize[i].fTypeName, gTypeSize[i].fSizeOf);
    }

#endif

    if (false)  // test asm fixmul
    {
        int j;
        SkMSec now = SkTime::GetMSecs();
        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkFixedMul_portable(0x8000, 0x150000);
        }
        SkMSec now2 = SkTime::GetMSecs();
        printf("-------- SkFixedMul_portable = %d\n", now2 - now);

        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkFixedMul(0x8000, 0x150000);
        }
        printf("-------- SkFixedMul = %d\n", SkTime::GetMSecs() - now2);

        SkRandom rand;
        for (j = 0; j < 10000; j++) {
            SkFixed a = rand.nextS() >> 8;
            SkFixed b = rand.nextS() >> 8;
            SkFixed c1 = SkFixedMul_portable(a, b);
            SkFixed c2 = SkFixedMul(a, b);
            if (SkAbs32(c1 - c2) > 1)
                printf("------ FixMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2);
        }
    }
    
    if (false)  // test asm fractmul
    {
        int j;
        SkMSec now = SkTime::GetMSecs();
        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkFractMul_portable(0x800000, 0x1500000);
        }
        SkMSec now2 = SkTime::GetMSecs();
        printf("-------- SkFractMul_portable = %d\n", now2 - now);

        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkFractMul(0x800000, 0x1500000);
        }
        printf("-------- SkFractMul = %d\n", SkTime::GetMSecs() - now2);

        SkRandom rand;
        for (j = 0; j < 10000; j++) {
            SkFixed a = rand.nextS() >> 1;
            SkFixed b = rand.nextS() >> 1;
            SkFixed c1 = SkFractMul_portable(a, b);
            SkFixed c2 = SkFractMul(a, b);
            if (SkAbs32(c1 - c2) > 1)
                printf("------ FractMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2);
        }
    }
    
    if (false)   // test asm clz
    {
        int j;
        SkMSec now = SkTime::GetMSecs();
        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkCLZ_portable(now);
        }
        SkMSec now2 = SkTime::GetMSecs();
        printf("-------- SkCLZ_portable = %d\n", now2 - now);

        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkCLZ(now);
        }
        printf("-------- SkCLZ = %d\n", SkTime::GetMSecs() - now2);

        SkRandom rand;
        for (j = 0; j < 10000; j++) {
            uint32_t a = rand.nextU();
            int c1 = SkCLZ_portable(a);
            int c2 = SkCLZ(a);
            if (c1 != c2)
                printf("------ CLZ disagreement: (%x) slow=%x fast=%x\n", a, c1, c2);
        }
    }
    
#ifdef SPEED_TEST
    if (false) {
        int i;
        int (*proc)(int);

        static const struct {
            int (*proc)(int);
            const char* name;
        } gList[] = {
            { test_s64, "Sk64" },
            { test_native_64, "native" }
        };

        for (size_t j = 0; j < SK_ARRAY_COUNT(gList); j++) {
            SkMSec now = SkTime::GetMSecs();
            proc = gList[j].proc;
            for (i = 0; i < BIG_LOOP_COUNT; i++) {
                proc(i);
            }
            printf("-------- %s = %d\n", gList[j].name, SkTime::GetMSecs() - now);
        }
    }
#endif

    if (false) {
        size_t i, size = 480;
        char* buffer = (char*)sk_malloc_throw(size);
        uint16_t* buffer16 = (uint16_t*)buffer;
        uint32_t* buffer32 = (uint32_t*)buffer;

        SkMSec now = SkTime::GetMSecs();
        for (i = 0; i < 100000; i++) {
            sk_memset16(buffer16, (uint16_t)i, size >> 1);
        }
        SkMSec now2 = SkTime::GetMSecs();
        for (i = 0; i < 100000; i++) {
            sk_memset16_portable(buffer16, (uint16_t)i, size >> 1);
        }
        SkMSec now3 = SkTime::GetMSecs();
        printf("----------- memset16: native %d, portable %d\n", now2 - now, now3 - now2);

        now = SkTime::GetMSecs();
        for (i = 0; i < 100000; i++) {
            sk_memset32(buffer32, i, size >> 2);
        }
        now2 = SkTime::GetMSecs();
        for (i = 0; i < 100000; i++) {
            sk_memset32_portable(buffer32, i, size >> 2);
        }
        now3 = SkTime::GetMSecs();
        printf("----------- memset32: native %d, portable %d\n", now2 - now, now3 - now2);
        
        sk_free(buffer);
    }
    
#ifdef SPEED_TEST
    if (false) {
        test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorBLACK);
        test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorRED);
        test_drawText(SkBitmap::kRGB_565_Config, SK_ColorBLACK);
        test_drawText(SkBitmap::kRGB_565_Config, SK_ColorRED);
    }
#endif
    
//    if (true) {
//        test_sort();
//    }
}

////////////////////////////////////////////////////////////////////////////

#include "SkGlyphCache.h"

void SkGraphics::Term() {
    SkGraphics::SetFontCacheUsed(0);
    SkGlobals::Term();
}

size_t SkGraphics::GetFontCacheUsed() {
    return SkGlyphCache::GetCacheUsed();
}

bool SkGraphics::SetFontCacheUsed(size_t usageInBytes) {
    return SkGlyphCache::SetCacheUsed(usageInBytes);
}

float dummy() { return 1.25f; }