SkGraphics.cpp revision 2043f7d009a795e164c58f4674e6b879aeb679c9
1/* libs/graphics/sgl/SkGraphics.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkGraphics.h"
19
20#include "Sk64.h"
21#include "SkBlitter.h"
22#include "SkCanvas.h"
23#include "SkFloat.h"
24#include "SkGeometry.h"
25#include "SkGlobals.h"
26#include "SkMath.h"
27#include "SkMatrix.h"
28#include "SkPath.h"
29#include "SkPathEffect.h"
30#include "SkRandom.h"
31#include "SkRefCnt.h"
32#include "SkScalerContext.h"
33#include "SkShader.h"
34#include "SkStream.h"
35#include "SkTSearch.h"
36#include "SkTime.h"
37#include "SkUtils.h"
38#include "SkXfermode.h"
39
40#if 0
41
42#define SK_SORT_TEMPLATE_TYPE       int
43#define SK_SORT_TEMPLATE_NAME       sort_int
44#define SK_SORT_TEMPLATE_CMP(a, b)   ((a) - (b))
45#include "SkSortTemplate.h"
46
47#define SK_SORT_TEMPLATE_TYPE       int*
48#define SK_SORT_TEMPLATE_NAME       sort_intptr
49#define SK_SORT_TEMPLATE_CMP(a, b)   (*(a) - *(b))
50#include "SkSortTemplate.h"
51
52static void test_sort()
53{
54    int array[] = { 4, 3, 7, 5, 2, 5, 1, 2, 9, 6, 7, 4, 5, 3, 1, 0 };
55    int* ptr[SK_ARRAY_COUNT(array)];
56    int i, N = SK_ARRAY_COUNT(array) - 1;
57
58    for (i = 0; i < N; i++)
59        printf(" %d", array[i]);
60    printf("\n");
61
62    for (i = 0; i < N; i++)
63        ptr[i] = &array[i];
64    sort_intptr(ptr, N);
65    for (i = 0; i < N; i++)
66        printf(" %d", *ptr[i]);
67    printf("\n");
68
69    sort_int(array, N);
70    for (i = 0; i < N; i++)
71        printf(" %d", array[i]);
72    printf("\n");
73
74}
75#endif
76
77#define SPEED_TESTx
78
79#define typesizeline(type)  { #type , sizeof(type) }
80
81
82#ifdef BUILD_EMBOSS_TABLE
83    extern void SkEmbossMask_BuildTable();
84#endif
85
86#ifdef BUILD_RADIALGRADIENT_TABLE
87    extern void SkRadialGradient_BuildTable();
88#endif
89
90#define BIG_LOOP_COUNT  1000000
91#define TEXT_LOOP_COUNT 1000
92
93#ifdef SPEED_TEST
94static int test_s64(int i)
95{
96    Sk64    a, b, c;
97
98    c.set(0);
99    a.set(i);
100    b.setMul(i, i);
101    a.add(b);
102    a.add(c);
103    return c.getFixed();
104}
105
106static int test_native_64(int i)
107{
108    int16_t    a, b, c;
109
110    c = 0;
111    a = i;
112    b = (int64_t)i * i;
113    a += b;
114    a += c;
115    return (int)(c >> 16);
116}
117
118static void test_drawText(SkBitmap::Config config, SkColor color)
119{
120    SkBitmap    bm;
121
122    bm.setConfig(config, 320, 240);
123    bm.allocPixels();
124
125    SkCanvas canvas(bm);
126    SkPaint  paint;
127
128    paint.setAntiAlias(true);
129    paint.setTextSize(SkIntToScalar(12));
130    paint.setColor(color);
131
132    SkScalar x = SkIntToScalar(20);
133    SkScalar y = SkIntToScalar(100);
134    const char* text = "Hamburgefons";
135    size_t      len = strlen(text);
136
137    // draw once to populate the cache
138    canvas.drawText(text, len, x, y, paint);
139
140    SkMSec now = SkTime::GetMSecs();
141    for (int i = 0; i < TEXT_LOOP_COUNT; i++)
142        canvas.drawText(text, len, x, y, paint);
143    printf("----------- Config: %d, Color=%x, CPS = %g\n", config, color,
144           len * TEXT_LOOP_COUNT * 1000.0 / (SkTime::GetMSecs() - now));
145}
146
147#endif
148
149#ifdef SK_CAN_USE_FLOAT
150#include "SkFloatBits.h"
151
152static inline float fast_inc(float x) {
153    SkFloatIntUnion data;
154    data.fFloat = x;
155    data.fSignBitInt += 1;
156    return data.fFloat;
157}
158
159extern float dummy();
160int time_math() {
161    SkMSec now;
162    int i;
163    int sum = 0;
164    const int repeat = 1000000;
165    float f;
166
167    f = dummy();
168    now = SkTime::GetMSecs();
169    for (i = repeat - 1; i >= 0; --i) {
170        sum += (int)f; f = fast_inc(f);
171        sum += (int)f; f = fast_inc(f);
172        sum += (int)f; f = fast_inc(f);
173        sum += (int)f; f = fast_inc(f);
174    }
175    SkDebugf("---- native cast %d\n", SkTime::GetMSecs() - now);
176
177    f = dummy();
178    now = SkTime::GetMSecs();
179    for (i = repeat - 1; i >= 0; --i) {
180        sum += SkFloatToIntCast(f); f = fast_inc(f);
181        sum += SkFloatToIntCast(f); f = fast_inc(f);
182        sum += SkFloatToIntCast(f); f = fast_inc(f);
183        sum += SkFloatToIntCast(f); f = fast_inc(f);
184    }
185    SkDebugf("---- hack cast %d\n", SkTime::GetMSecs() - now);
186
187    f = dummy();
188    now = SkTime::GetMSecs();
189    for (i = repeat - 1; i >= 0; --i) {
190        sum += (int)sk_float_floor(f + 0.5f); f = fast_inc(f);
191        sum += (int)sk_float_floor(f + 0.5f); f = fast_inc(f);
192        sum += (int)sk_float_floor(f + 0.5f); f = fast_inc(f);
193        sum += (int)sk_float_floor(f + 0.5f); f = fast_inc(f);
194    }
195    SkDebugf("---- native round %d\n", SkTime::GetMSecs() - now);
196
197    f = dummy();
198    now = SkTime::GetMSecs();
199    for (i = repeat - 1; i >= 0; --i) {
200        sum += SkFloatToIntRound(f); f = fast_inc(f);
201        sum += SkFloatToIntRound(f); f = fast_inc(f);
202        sum += SkFloatToIntRound(f); f = fast_inc(f);
203        sum += SkFloatToIntRound(f); f = fast_inc(f);
204    }
205    SkDebugf("---- hack round %d\n", SkTime::GetMSecs() - now);
206
207    f = dummy();
208    now = SkTime::GetMSecs();
209    for (i = repeat - 1; i >= 0; --i) {
210        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
211        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
212        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
213        sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
214    }
215    SkDebugf("---- native floor %d\n", SkTime::GetMSecs() - now);
216
217    f = dummy();
218    now = SkTime::GetMSecs();
219    for (i = repeat - 1; i >= 0; --i) {
220        sum += SkFloatToIntFloor(f); f = fast_inc(f);
221        sum += SkFloatToIntFloor(f); f = fast_inc(f);
222        sum += SkFloatToIntFloor(f); f = fast_inc(f);
223        sum += SkFloatToIntFloor(f); f = fast_inc(f);
224    }
225    SkDebugf("---- hack floor %d\n", SkTime::GetMSecs() - now);
226
227    return sum;
228}
229
230#if 0
231static float time_intToFloat() {
232    const int repeat = 1000000;
233    int i, n;
234    SkMSec now;
235    float sum = 0;
236
237    n = (int)dummy();
238    now = SkTime::GetMSecs();
239    for (i = repeat - 1; i >= 0; --i) {
240        sum += (float)n; n += 1;
241        sum += (float)n; n += 1;
242        sum += (float)n; n += 1;
243        sum += (float)n; n += 1;
244    }
245    SkDebugf("---- native i2f %d\n", SkTime::GetMSecs() - now);
246
247    n = (int)dummy();
248    now = SkTime::GetMSecs();
249    for (i = repeat - 1; i >= 0; --i) {
250        sum += SkIntToFloatCast(n); n += 1;
251        sum += SkIntToFloatCast(n); n += 1;
252        sum += SkIntToFloatCast(n); n += 1;
253        sum += SkIntToFloatCast(n); n += 1;
254    }
255    SkDebugf("---- check i2f %d\n", SkTime::GetMSecs() - now);
256
257    n = (int)dummy();
258    now = SkTime::GetMSecs();
259    for (i = repeat - 1; i >= 0; --i) {
260        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
261        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
262        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
263        sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
264    }
265    SkDebugf("---- nocheck i2f %d\n", SkTime::GetMSecs() - now);
266
267    return sum;
268}
269#endif
270#endif
271
272void SkGraphics::Init()
273{
274    SkGlobals::Init();
275
276#ifdef SK_CAN_USE_FLOAT
277//    time_math();
278//    time_intToFloat();
279#endif
280
281#ifdef BUILD_EMBOSS_TABLE
282    SkEmbossMask_BuildTable();
283#endif
284#ifdef BUILD_RADIALGRADIENT_TABLE
285    SkRadialGradient_BuildTable();
286#endif
287
288#ifdef SK_DEBUGx
289    int i;
290
291    static const struct {
292        const char* fTypeName;
293        size_t      fSizeOf;
294    } gTypeSize[] = {
295        typesizeline(char),
296        typesizeline(short),
297        typesizeline(int),
298        typesizeline(long),
299        typesizeline(size_t),
300        typesizeline(void*),
301
302        typesizeline(S8CPU),
303        typesizeline(U8CPU),
304        typesizeline(S16CPU),
305        typesizeline(U16CPU),
306
307        typesizeline(SkPoint),
308        typesizeline(SkRect),
309        typesizeline(SkMatrix),
310        typesizeline(SkPath),
311        typesizeline(SkGlyph),
312        typesizeline(SkRefCnt),
313
314        typesizeline(SkPaint),
315        typesizeline(SkCanvas),
316        typesizeline(SkBlitter),
317        typesizeline(SkShader),
318        typesizeline(SkXfermode),
319        typesizeline(SkPathEffect)
320    };
321
322#ifdef SK_CPU_BENDIAN
323    SkDebugf("SkGraphics: big-endian\n");
324#else
325    SkDebugf("SkGraphics: little-endian\n");
326#endif
327
328    {
329        char    test = 0xFF;
330        int     itest = test;   // promote to int, see if it sign-extended
331        if (itest < 0)
332            SkDebugf("SkGraphics: char is signed\n");
333        else
334            SkDebugf("SkGraphics: char is unsigned\n");
335    }
336    for (i = 0; i < (int)SK_ARRAY_COUNT(gTypeSize); i++) {
337        SkDebugf("SkGraphics: sizeof(%s) = %d\n",
338                 gTypeSize[i].fTypeName, gTypeSize[i].fSizeOf);
339    }
340
341#endif
342
343    if (false)  // test asm fixmul
344    {
345        int j;
346        SkMSec now = SkTime::GetMSecs();
347        for (j = 0; j < BIG_LOOP_COUNT; j++) {
348            (void)SkFixedMul_portable(0x8000, 0x150000);
349        }
350        SkMSec now2 = SkTime::GetMSecs();
351        printf("-------- SkFixedMul_portable = %d\n", now2 - now);
352
353        for (j = 0; j < BIG_LOOP_COUNT; j++) {
354            (void)SkFixedMul(0x8000, 0x150000);
355        }
356        printf("-------- SkFixedMul = %d\n", SkTime::GetMSecs() - now2);
357
358        SkRandom rand;
359        for (j = 0; j < 10000; j++) {
360            SkFixed a = rand.nextS() >> 8;
361            SkFixed b = rand.nextS() >> 8;
362            SkFixed c1 = SkFixedMul_portable(a, b);
363            SkFixed c2 = SkFixedMul(a, b);
364            if (SkAbs32(c1 - c2) > 1)
365                printf("------ FixMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2);
366        }
367    }
368
369    if (false)  // test asm fractmul
370    {
371        int j;
372        SkMSec now = SkTime::GetMSecs();
373        for (j = 0; j < BIG_LOOP_COUNT; j++) {
374            (void)SkFractMul_portable(0x800000, 0x1500000);
375        }
376        SkMSec now2 = SkTime::GetMSecs();
377        printf("-------- SkFractMul_portable = %d\n", now2 - now);
378
379        for (j = 0; j < BIG_LOOP_COUNT; j++) {
380            (void)SkFractMul(0x800000, 0x1500000);
381        }
382        printf("-------- SkFractMul = %d\n", SkTime::GetMSecs() - now2);
383
384        SkRandom rand;
385        for (j = 0; j < 10000; j++) {
386            SkFixed a = rand.nextS() >> 1;
387            SkFixed b = rand.nextS() >> 1;
388            SkFixed c1 = SkFractMul_portable(a, b);
389            SkFixed c2 = SkFractMul(a, b);
390            if (SkAbs32(c1 - c2) > 1)
391                printf("------ FractMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2);
392        }
393    }
394
395    if (false)   // test asm clz
396    {
397        int j;
398        SkMSec now = SkTime::GetMSecs();
399        for (j = 0; j < BIG_LOOP_COUNT; j++) {
400            (void)SkCLZ_portable(now);
401        }
402        SkMSec now2 = SkTime::GetMSecs();
403        printf("-------- SkCLZ_portable = %d\n", now2 - now);
404
405        for (j = 0; j < BIG_LOOP_COUNT; j++) {
406            (void)SkCLZ(now);
407        }
408        printf("-------- SkCLZ = %d\n", SkTime::GetMSecs() - now2);
409
410        SkRandom rand;
411        for (j = 0; j < 10000; j++) {
412            uint32_t a = rand.nextU();
413            int c1 = SkCLZ_portable(a);
414            int c2 = SkCLZ(a);
415            if (c1 != c2)
416                printf("------ CLZ disagreement: (%x) slow=%x fast=%x\n", a, c1, c2);
417        }
418    }
419
420#ifdef SPEED_TEST
421    if (false) {
422        int i;
423        int (*proc)(int);
424
425        static const struct {
426            int (*proc)(int);
427            const char* name;
428        } gList[] = {
429            { test_s64, "Sk64" },
430            { test_native_64, "native" }
431        };
432
433        for (size_t j = 0; j < SK_ARRAY_COUNT(gList); j++) {
434            SkMSec now = SkTime::GetMSecs();
435            proc = gList[j].proc;
436            for (i = 0; i < BIG_LOOP_COUNT; i++) {
437                proc(i);
438            }
439            printf("-------- %s = %d\n", gList[j].name, SkTime::GetMSecs() - now);
440        }
441    }
442#endif
443
444    if (false) {
445        size_t i, size = 480;
446        char* buffer = (char*)sk_malloc_throw(size);
447        uint16_t* buffer16 = (uint16_t*)buffer;
448        uint32_t* buffer32 = (uint32_t*)buffer;
449
450        SkMSec now = SkTime::GetMSecs();
451        for (i = 0; i < 100000; i++) {
452            sk_memset16(buffer16, (uint16_t)i, size >> 1);
453        }
454        SkMSec now2 = SkTime::GetMSecs();
455        for (i = 0; i < 100000; i++) {
456            sk_memset16_portable(buffer16, (uint16_t)i, size >> 1);
457        }
458        SkMSec now3 = SkTime::GetMSecs();
459        printf("----------- memset16: native %d, portable %d\n", now2 - now, now3 - now2);
460
461        now = SkTime::GetMSecs();
462        for (i = 0; i < 100000; i++) {
463            sk_memset32(buffer32, i, size >> 2);
464        }
465        now2 = SkTime::GetMSecs();
466        for (i = 0; i < 100000; i++) {
467            sk_memset32_portable(buffer32, i, size >> 2);
468        }
469        now3 = SkTime::GetMSecs();
470        printf("----------- memset32: native %d, portable %d\n", now2 - now, now3 - now2);
471
472        sk_free(buffer);
473    }
474
475#ifdef SPEED_TEST
476    if (false) {
477        test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorBLACK);
478        test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorRED);
479        test_drawText(SkBitmap::kRGB_565_Config, SK_ColorBLACK);
480        test_drawText(SkBitmap::kRGB_565_Config, SK_ColorRED);
481    }
482#endif
483
484//    if (true) {
485//        test_sort();
486//    }
487}
488
489////////////////////////////////////////////////////////////////////////////
490
491#include "SkGlyphCache.h"
492
493void SkGraphics::Term() {
494    SkGraphics::SetFontCacheUsed(0);
495    SkGlobals::Term();
496}
497
498size_t SkGraphics::GetFontCacheUsed() {
499    return SkGlyphCache::GetCacheUsed();
500}
501
502bool SkGraphics::SetFontCacheUsed(size_t usageInBytes) {
503    return SkGlyphCache::SetCacheUsed(usageInBytes);
504}
505
506float dummy() { return 1.25f; }
507