From cb5701ecfa08563037c24cc7b8ed4bb2629ef70b Mon Sep 17 00:00:00 2001 From: Xin Qi Date: Thu, 27 Dec 2012 11:19:52 -0800 Subject: Several skia tunings for JB_2.5 * Optiming constructor of Paint object * Special copy path for small object * Global Language list instead of constructing a new obj everytime. Change-Id: I8d4687fffe055166a4758059872af09bfdc973d4 --- include/core/SkDraw.h | 2 + include/core/SkPaint.h | 28 +++++++++++- include/core/SkRect.h | 11 +++++ src/core/SkDraw.cpp | 18 +++++++- src/core/SkPaint.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 174 insertions(+), 7 deletions(-) diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h index 8c659c2..ae323f2 100644 --- a/include/core/SkDraw.h +++ b/include/core/SkDraw.h @@ -104,6 +104,8 @@ private: void drawBitmapAsMask(const SkBitmap&, const SkPaint&) const; public: + //Be noted to update SkDraw::SkDraw() constructor code when struture is + //change! const SkBitmap* fBitmap; // required const SkMatrix* fMatrix; // required const SkRegion* fClip; // DEPRECATED diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index d2233f0..88f26f1 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -17,6 +17,7 @@ #include "SkString.h" #ifdef SK_BUILD_FOR_ANDROID +#include #include "SkLanguage.h" #endif @@ -42,6 +43,26 @@ typedef const SkGlyph& (*SkDrawCacheProc)(SkGlyphCache*, const char**, typedef const SkGlyph& (*SkMeasureCacheProc)(SkGlyphCache*, const char**); +class SkLangList { + public: + SkLangList(); + + SkLanguage s; + SkLangList *next; +}; + +class SkLanguages { +public: + SkLanguages(); + SkLangList * setLanguage( const SkLanguage& locale ); + const SkLanguage& getLanguage( SkLangList * t ) const; + +private: + SkLangList * LocaleArray; + pthread_mutex_t update_mutex; +}; + + /** \class SkPaint The SkPaint class holds the style and color information about how to draw @@ -664,7 +685,8 @@ public: /** Return the paint's language value used for drawing text. @return the paint's language value used for drawing text. */ - const SkLanguage& getLanguage() const { return fLanguage; } + const SkLanguage& getLanguage() const; + /** Set the paint's language value used for drawing text. @param language set the paint's language value for drawing text. @@ -904,6 +926,8 @@ public: bool nothingToDraw() const; private: + //Be noted to update SkPaint::SkPaint(const SkPaint& src) copy + //constructor when struture is changed for fast path! SkTypeface* fTypeface; SkScalar fTextSize; SkScalar fTextScaleX; @@ -929,7 +953,7 @@ private: unsigned fTextEncoding : 2; // 3 values unsigned fHinting : 2; #ifdef SK_BUILD_FOR_ANDROID - SkLanguage fLanguage; + SkLangList* fpLanguage; FontVariant fFontVariant; #endif diff --git a/include/core/SkRect.h b/include/core/SkRect.h index 65e7611..64568c9 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -347,6 +347,16 @@ struct SK_API SkRect { */ bool isFinite() const { #ifdef SK_SCALAR_IS_FLOAT +#if defined(KRAIT_OPTIMIZATION) + if (SkScalarIsFinite(fBottom) && + SkScalarIsFinite(fRight) && + SkScalarIsFinite(fLeft) && + SkScalarIsFinite(fTop)) { + return true; + } else { + return false; + } +#else // x * 0 will be NaN iff x is infinity or NaN. // a + b will be NaN iff either a or b is NaN. float value = fLeft * 0 + fTop * 0 + fRight * 0 + fBottom * 0; @@ -354,6 +364,7 @@ struct SK_API SkRect { // value is either NaN or it is finite (zero). // value==value will be true iff value is not NaN return value == value; +#endif #else // use bit-or for speed, since we don't care about short-circuting the // tests, and we expect the common case will be that we need to check all. diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 23a6d59..19337f7 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -114,7 +114,23 @@ private: /////////////////////////////////////////////////////////////////////////////// SkDraw::SkDraw() { - sk_bzero(this, sizeof(*this)); + //Be noted to update this field when struture is changed! + if( sizeof(*this) == 40 ){ + fBitmap = NULL; + fMatrix = NULL; + fClip = NULL; + fRC = NULL; + + fClipStack = NULL; + fDevice = NULL; + fBounder = NULL; + fProcs = NULL; + + fMVMatrix = NULL; + fExtMatrix = NULL; + } else { + sk_bzero(this, sizeof(*this)); + } } SkDraw::SkDraw(const SkDraw& src) { diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 35b5b38..a701ba5 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -27,6 +27,76 @@ #include "SkGlyphCache.h" #include "SkPaintDefaults.h" +#include + +SkLangList::SkLangList(){ + new(&s) SkLanguage(); + next = NULL; +} + +static class SkLanguages gLanguages; + +SkLanguages::SkLanguages(){ + LocaleArray = NULL; + update_mutex = PTHREAD_MUTEX_INITIALIZER; +} + +SkLangList * SkLanguages::setLanguage( const SkLanguage& lang ){ +start: + if( !LocaleArray ){ + pthread_mutex_lock( &update_mutex ); + if( !LocaleArray ){ + LocaleArray = new SkLangList(); + LocaleArray->s = lang; + pthread_mutex_unlock( &update_mutex ); + return LocaleArray; + } else { + pthread_mutex_unlock( &update_mutex ); + goto start; + } + + } + + SkLangList * l = LocaleArray; + SkLangList * prev = LocaleArray; + while( l ){ + if( l->s == lang ){ + return l; + } + prev = l; + l = l->next; + } + + pthread_mutex_lock( &update_mutex ); + + SkDebugf("new locale %s", lang.getTag().c_str()); + //Within mutex, restart from beginning + l = LocaleArray; + prev = LocaleArray; + while( l ){ + if( l->s == lang ){ + pthread_mutex_unlock( &update_mutex ); + return l; + } + prev = l; + l = l->next; + } + l = new SkLangList(); + prev->next = l; + l->s = lang; + + pthread_mutex_unlock( &update_mutex ); + + return l; +} + + +const SkLanguage& SkLanguages::getLanguage( SkLangList * t ) const { + return t->s; +} + + + // define this to get a printf for out-of-range parameter in setters // e.g. setTextSize(-1) //#define SK_REPORT_API_RANGE_CHECK @@ -72,14 +142,40 @@ SkPaint::SkPaint() { fTextEncoding = kUTF8_TextEncoding; fHinting = SkPaintDefaults_Hinting; #ifdef SK_BUILD_FOR_ANDROID - fLanguage = SkLanguage(); fFontVariant = kDefault_Variant; fGenerationID = 0; #endif } +extern "C" { + //Hard coded copy with size of 76 bytes. This will avoid the extra cost + //of size checking branching in generic memcpy code + inline void memcpy_76(int* src, int* dst) { + __asm__ volatile ("cpy r4, %1 \n" + "cpy r5, %0 \n" + "ldm r4!, {r0-r3} \n" + "cpy r12, r5 \n" + "stm r12!,{r0-r3} \n" + "ldm r4!, {r0-r3} \n" + "stm r12!,{r0-r3} \n" + "ldm r4!, {r0-r3} \n" + "stm r12!,{r0-r3} \n" + "ldm r4!, {r0-r3} \n" + "stm r12!,{r0-r3} \n" + "ldm r4, {r0-r2} \n" + "stm r12, {r0-r2} \n" + : + : "r" (src), "r" (dst) + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r12"); + } +} SkPaint::SkPaint(const SkPaint& src) { - memcpy(this, &src, sizeof(src)); + //Note: need to update this when SkPaint struture/size is changed! + if(sizeof(src) == 76){ + memcpy_76((int*)this, (int*)&src); + } else { + memcpy((int*)this, (int*)&src, sizeof(src)); + } SkSafeRef(fTypeface); SkSafeRef(fPathEffect); @@ -364,12 +460,30 @@ void SkPaint::setTextEncoding(TextEncoding encoding) { #ifdef SK_BUILD_FOR_ANDROID void SkPaint::setLanguage(const SkLanguage& language) { - if(fLanguage != language) { - fLanguage = language; + SkLangList* oldpLanguage = fpLanguage; + fpLanguage = gLanguages.setLanguage(language); + if (oldpLanguage != fpLanguage) { GEN_ID_INC; } } +const SkLanguage& SkPaint::getLanguage() const { + if(!fpLanguage){ + //Add the default empty language + //We shouldn't go through this path anyway + SkLanguage l = SkLanguage(""); + SkLangList* fpl; + //We can NOT assign the return pointer to fpLanguage as the API is + //defined on the READ-ONLY object. + fpl = gLanguages.setLanguage(l); + //This is persistent object in the global array, + //So there is no memory leak + return fpl->s; + } else { + return fpLanguage->s; + } +} + void SkPaint::setFontVariant(FontVariant fontVariant) { if ((unsigned)fontVariant <= kLast_Variant) { GEN_ID_INC_EVAL((unsigned)fontVariant != fFontVariant); -- cgit v1.1