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
52 static 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
test_s64(int i)94 static 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
test_native_64(int i)106 static 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
test_drawText(SkBitmap::Config config,SkColor color)118 static 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
fast_inc(float x)152 static inline float fast_inc(float x) {
153 SkFloatIntUnion data;
154 data.fFloat = x;
155 data.fSignBitInt += 1;
156 return data.fFloat;
157 }
158
159 extern float dummy();
time_math()160 int 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
231 static 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
Init()272 void 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
Term()493 void SkGraphics::Term() {
494 SkGraphics::SetFontCacheUsed(0);
495 SkGlobals::Term();
496 }
497
GetFontCacheUsed()498 size_t SkGraphics::GetFontCacheUsed() {
499 return SkGlyphCache::GetCacheUsed();
500 }
501
SetFontCacheUsed(size_t usageInBytes)502 bool SkGraphics::SetFontCacheUsed(size_t usageInBytes) {
503 return SkGlyphCache::SetCacheUsed(usageInBytes);
504 }
505
dummy()506 float dummy() { return 1.25f; }
507