blob: 64fbab90a1149d484abcacbf0adb5df3dd69c3e4 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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 "SkPathMeasure.h"
31#include "SkRandom.h"
32#include "SkRefCnt.h"
33#include "SkScalerContext.h"
34#include "SkShader.h"
35#include "SkStream.h"
36#include "SkTSearch.h"
37#include "SkTime.h"
38#include "SkUtils.h"
39#include "SkXfermode.h"
40
41#if 0
42
43#define SK_SORT_TEMPLATE_TYPE int
44#define SK_SORT_TEMPLATE_NAME sort_int
45#define SK_SORT_TEMPLATE_CMP(a, b) ((a) - (b))
46#include "SkSortTemplate.h"
47
48#define SK_SORT_TEMPLATE_TYPE int*
49#define SK_SORT_TEMPLATE_NAME sort_intptr
50#define SK_SORT_TEMPLATE_CMP(a, b) (*(a) - *(b))
51#include "SkSortTemplate.h"
52
53static void test_sort()
54{
55 int array[] = { 4, 3, 7, 5, 2, 5, 1, 2, 9, 6, 7, 4, 5, 3, 1, 0 };
56 int* ptr[SK_ARRAY_COUNT(array)];
57 int i, N = SK_ARRAY_COUNT(array) - 1;
58
59 for (i = 0; i < N; i++)
60 printf(" %d", array[i]);
61 printf("\n");
62
63 for (i = 0; i < N; i++)
64 ptr[i] = &array[i];
65 sort_intptr(ptr, N);
66 for (i = 0; i < N; i++)
67 printf(" %d", *ptr[i]);
68 printf("\n");
69
70 sort_int(array, N);
71 for (i = 0; i < N; i++)
72 printf(" %d", array[i]);
73 printf("\n");
74
75}
76#endif
77
78#define SPEED_TESTx
79
80#define typesizeline(type) { #type , sizeof(type) }
81#define unittestline(type) { #type , type::UnitTest }
82
83
84#ifdef BUILD_EMBOSS_TABLE
85 extern void SkEmbossMask_BuildTable();
86#endif
87
88#ifdef BUILD_RADIALGRADIENT_TABLE
89 extern void SkRadialGradient_BuildTable();
90#endif
91
92#define BIG_LOOP_COUNT 1000000
93#define TEXT_LOOP_COUNT 1000
94
95#ifdef SPEED_TEST
96static int test_s64(int i)
97{
98 Sk64 a, b, c;
99
100 c.set(0);
101 a.set(i);
102 b.setMul(i, i);
103 a.add(b);
104 a.add(c);
105 return c.getFixed();
106}
107
108static int test_native_64(int i)
109{
110 int16_t a, b, c;
111
112 c = 0;
113 a = i;
114 b = (int64_t)i * i;
115 a += b;
116 a += c;
117 return (int)(c >> 16);
118}
119
120static void test_drawText(SkBitmap::Config config, SkColor color)
121{
122 SkBitmap bm;
123
124 bm.setConfig(config, 320, 240);
125 bm.allocPixels();
126
127 SkCanvas canvas(bm);
128 SkPaint paint;
129
130 paint.setAntiAlias(true);
131 paint.setTextSize(SkIntToScalar(12));
132 paint.setColor(color);
133
134 SkScalar x = SkIntToScalar(20);
135 SkScalar y = SkIntToScalar(100);
136 const char* text = "Hamburgefons";
137 size_t len = strlen(text);
138
139 // draw once to populate the cache
140 canvas.drawText(text, len, x, y, paint);
141
142 SkMSec now = SkTime::GetMSecs();
143 for (int i = 0; i < TEXT_LOOP_COUNT; i++)
144 canvas.drawText(text, len, x, y, paint);
145 printf("----------- Config: %d, Color=%x, CPS = %g\n", config, color,
146 len * TEXT_LOOP_COUNT * 1000.0 / (SkTime::GetMSecs() - now));
147}
148
149#endif
150
151#include "SkFloatBits.h"
152
153static inline float fast_inc(float x) {
154 SkFloatIntUnion data;
155 data.fFloat = x;
156 data.fSignBitInt += 1;
157 return data.fFloat;
158}
159
160extern float dummy();
161int time_math() {
162 SkMSec now;
163 int i;
164 int sum = 0;
165 const int repeat = 1000000;
166 float f;
167
168 f = dummy();
169 now = SkTime::GetMSecs();
170 for (i = repeat - 1; i >= 0; --i) {
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 sum += (int)f; f = fast_inc(f);
175 }
176 SkDebugf("---- native cast %d\n", SkTime::GetMSecs() - now);
177
178 f = dummy();
179 now = SkTime::GetMSecs();
180 for (i = repeat - 1; i >= 0; --i) {
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 sum += SkFloatToIntCast(f); f = fast_inc(f);
185 }
186 SkDebugf("---- hack cast %d\n", SkTime::GetMSecs() - now);
187
188 f = dummy();
189 now = SkTime::GetMSecs();
190 for (i = repeat - 1; i >= 0; --i) {
191 sum += (int)floorf(f + 0.5f); f = fast_inc(f);
192 sum += (int)floorf(f + 0.5f); f = fast_inc(f);
193 sum += (int)floorf(f + 0.5f); f = fast_inc(f);
194 sum += (int)floorf(f + 0.5f); f = fast_inc(f);
195 }
196 SkDebugf("---- native round %d\n", SkTime::GetMSecs() - now);
197
198 f = dummy();
199 now = SkTime::GetMSecs();
200 for (i = repeat - 1; i >= 0; --i) {
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 sum += SkFloatToIntRound(f); f = fast_inc(f);
205 }
206 SkDebugf("---- hack round %d\n", SkTime::GetMSecs() - now);
207
208 f = dummy();
209 now = SkTime::GetMSecs();
210 for (i = repeat - 1; i >= 0; --i) {
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 sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
215 }
216 SkDebugf("---- native floor %d\n", SkTime::GetMSecs() - now);
217
218 f = dummy();
219 now = SkTime::GetMSecs();
220 for (i = repeat - 1; i >= 0; --i) {
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 sum += SkFloatToIntFloor(f); f = fast_inc(f);
225 }
226 SkDebugf("---- hack floor %d\n", SkTime::GetMSecs() - now);
227
228 return sum;
229}
230
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
270void SkGraphics::Init(bool runUnitTests)
271{
272 SkGlobals::Init();
273
274// time_math();
275// time_intToFloat();
276
277#ifdef BUILD_EMBOSS_TABLE
278 SkEmbossMask_BuildTable();
279#endif
280#ifdef BUILD_RADIALGRADIENT_TABLE
281 SkRadialGradient_BuildTable();
282#endif
283
284#ifdef SK_SUPPORT_UNITTEST
285 if (runUnitTests == false)
286 return;
287 int i;
288
289 static const struct {
290 const char* fTypeName;
291 size_t fSizeOf;
292 } gTypeSize[] = {
293 typesizeline(char),
294 typesizeline(short),
295 typesizeline(int),
296 typesizeline(long),
297 typesizeline(size_t),
298 typesizeline(void*),
299
300 typesizeline(S8CPU),
301 typesizeline(U8CPU),
302 typesizeline(S16CPU),
303 typesizeline(U16CPU),
304
305 typesizeline(SkPoint),
306 typesizeline(SkRect),
307 typesizeline(SkMatrix),
308 typesizeline(SkPath),
309 typesizeline(SkGlyph),
310 typesizeline(SkRefCnt),
311
312 typesizeline(SkPaint),
313 typesizeline(SkCanvas),
314 typesizeline(SkBlitter),
315 typesizeline(SkShader),
316 typesizeline(SkXfermode),
317 typesizeline(SkPathEffect)
318 };
319
320#ifdef SK_CPU_BENDIAN
321 SkDebugf("SkGraphics: big-endian\n");
322#else
323 SkDebugf("SkGraphics: little-endian\n");
324#endif
325
326 {
327 char test = 0xFF;
328 int itest = test; // promote to int, see if it sign-extended
329 if (itest < 0)
330 SkDebugf("SkGraphics: char is signed\n");
331 else
332 SkDebugf("SkGraphics: char is unsigned\n");
333 }
334 for (i = 0; i < (int)SK_ARRAY_COUNT(gTypeSize); i++)
335 SkDebugf("SkGraphics: sizeof(%s) = %d\n", gTypeSize[i].fTypeName, gTypeSize[i].fSizeOf);
336
337 static const struct {
338 const char* fTypeName;
339 void (*fUnitTest)();
340 } gUnitTests[] = {
341 unittestline(Sk64),
342 unittestline(SkMath),
343 unittestline(SkUtils),
344 unittestline(SkString),
345 unittestline(SkMatrix),
346 unittestline(SkGeometry),
347 unittestline(SkPath),
348 unittestline(SkPathMeasure),
349 unittestline(SkStream),
350 unittestline(SkWStream),
351 };
352
353 for (i = 0; i < (int)SK_ARRAY_COUNT(gUnitTests); i++)
354 {
355 SkDebugf("SkGraphics: Running UnitTest for %s\n", gUnitTests[i].fTypeName);
356 gUnitTests[i].fUnitTest();
357 SkDebugf("SkGraphics: End UnitTest for %s\n", gUnitTests[i].fTypeName);
358 }
359 SkQSort_UnitTest();
360
361#endif
362
363 if (false) // test asm fixmul
364 {
365 int j;
366 SkMSec now = SkTime::GetMSecs();
367 for (j = 0; j < BIG_LOOP_COUNT; j++) {
368 (void)SkFixedMul_portable(0x8000, 0x150000);
369 }
370 SkMSec now2 = SkTime::GetMSecs();
371 printf("-------- SkFixedMul_portable = %d\n", now2 - now);
372
373 for (j = 0; j < BIG_LOOP_COUNT; j++) {
374 (void)SkFixedMul(0x8000, 0x150000);
375 }
376 printf("-------- SkFixedMul = %d\n", SkTime::GetMSecs() - now2);
377
378 SkRandom rand;
379 for (j = 0; j < 10000; j++) {
380 SkFixed a = rand.nextS() >> 8;
381 SkFixed b = rand.nextS() >> 8;
382 SkFixed c1 = SkFixedMul_portable(a, b);
383 SkFixed c2 = SkFixedMul(a, b);
384 if (SkAbs32(c1 - c2) > 1)
385 printf("------ FixMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2);
386 }
387 }
388
389 if (false) // test asm fractmul
390 {
391 int j;
392 SkMSec now = SkTime::GetMSecs();
393 for (j = 0; j < BIG_LOOP_COUNT; j++) {
394 (void)SkFractMul_portable(0x800000, 0x1500000);
395 }
396 SkMSec now2 = SkTime::GetMSecs();
397 printf("-------- SkFractMul_portable = %d\n", now2 - now);
398
399 for (j = 0; j < BIG_LOOP_COUNT; j++) {
400 (void)SkFractMul(0x800000, 0x1500000);
401 }
402 printf("-------- SkFractMul = %d\n", SkTime::GetMSecs() - now2);
403
404 SkRandom rand;
405 for (j = 0; j < 10000; j++) {
406 SkFixed a = rand.nextS() >> 1;
407 SkFixed b = rand.nextS() >> 1;
408 SkFixed c1 = SkFractMul_portable(a, b);
409 SkFixed c2 = SkFractMul(a, b);
410 if (SkAbs32(c1 - c2) > 1)
411 printf("------ FractMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2);
412 }
413 }
414
415 if (false) // test asm clz
416 {
417 int j;
418 SkMSec now = SkTime::GetMSecs();
419 for (j = 0; j < BIG_LOOP_COUNT; j++) {
420 (void)SkCLZ_portable(now);
421 }
422 SkMSec now2 = SkTime::GetMSecs();
423 printf("-------- SkCLZ_portable = %d\n", now2 - now);
424
425 for (j = 0; j < BIG_LOOP_COUNT; j++) {
426 (void)SkCLZ(now);
427 }
428 printf("-------- SkCLZ = %d\n", SkTime::GetMSecs() - now2);
429
430 SkRandom rand;
431 for (j = 0; j < 10000; j++) {
432 uint32_t a = rand.nextU();
433 int c1 = SkCLZ_portable(a);
434 int c2 = SkCLZ(a);
435 if (c1 != c2)
436 printf("------ CLZ disagreement: (%x) slow=%x fast=%x\n", a, c1, c2);
437 }
438 }
439
440#ifdef SPEED_TEST
441 if (false) {
442 int i;
443 int (*proc)(int);
444
445 static const struct {
446 int (*proc)(int);
447 const char* name;
448 } gList[] = {
449 { test_s64, "Sk64" },
450 { test_native_64, "native" }
451 };
452
453 for (size_t j = 0; j < SK_ARRAY_COUNT(gList); j++) {
454 SkMSec now = SkTime::GetMSecs();
455 proc = gList[j].proc;
456 for (i = 0; i < BIG_LOOP_COUNT; i++) {
457 proc(i);
458 }
459 printf("-------- %s = %d\n", gList[j].name, SkTime::GetMSecs() - now);
460 }
461 }
462#endif
463
464 if (false) {
465 size_t i, size = 480;
466 char* buffer = (char*)sk_malloc_throw(size);
467 uint16_t* buffer16 = (uint16_t*)buffer;
468 uint32_t* buffer32 = (uint32_t*)buffer;
469
470 SkMSec now = SkTime::GetMSecs();
471 for (i = 0; i < 100000; i++) {
472 sk_memset16(buffer16, (uint16_t)i, size >> 1);
473 }
474 SkMSec now2 = SkTime::GetMSecs();
475 for (i = 0; i < 100000; i++) {
476 sk_memset16_portable(buffer16, (uint16_t)i, size >> 1);
477 }
478 SkMSec now3 = SkTime::GetMSecs();
479 printf("----------- memset16: native %d, portable %d\n", now2 - now, now3 - now2);
480
481 now = SkTime::GetMSecs();
482 for (i = 0; i < 100000; i++) {
483 sk_memset32(buffer32, i, size >> 2);
484 }
485 now2 = SkTime::GetMSecs();
486 for (i = 0; i < 100000; i++) {
487 sk_memset32_portable(buffer32, i, size >> 2);
488 }
489 now3 = SkTime::GetMSecs();
490 printf("----------- memset32: native %d, portable %d\n", now2 - now, now3 - now2);
491
492 sk_free(buffer);
493 }
494
495#ifdef SPEED_TEST
496 if (false) {
497 test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorBLACK);
498 test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorRED);
499 test_drawText(SkBitmap::kRGB_565_Config, SK_ColorBLACK);
500 test_drawText(SkBitmap::kRGB_565_Config, SK_ColorRED);
501 }
502#endif
503
504// if (true) {
505// test_sort();
506// }
507}
508
509////////////////////////////////////////////////////////////////////////////
510
511#include "SkGlyphCache.h"
512
513void SkGraphics::Term() {
514 SkGraphics::SetFontCacheUsed(0);
515 SkGlobals::Term();
516}
517
518size_t SkGraphics::GetFontCacheUsed() {
519 return SkGlyphCache::GetCacheUsed();
520}
521
522bool SkGraphics::SetFontCacheUsed(size_t usageInBytes) {
523 return SkGlyphCache::SetCacheUsed(usageInBytes);
524}
525
526float dummy() { return 1.25f; }