Loading libs/hwui/SkiaInterpolator.cpp +48 −23 Original line number Diff line number Diff line Loading @@ -18,9 +18,8 @@ #include "include/core/SkScalar.h" #include "include/core/SkTypes.h" #include "include/private/SkFixed.h" #include "src/core/SkTSearch.h" #include <cstdlib> #include <log/log.h> typedef int Dot14; Loading @@ -41,18 +40,18 @@ static inline Dot14 pin_and_convert(float x) { if (x <= 0) { return 0; } if (x >= SK_Scalar1) { if (x >= 1.0f) { return Dot14_ONE; } return SkScalarToFixed(x) >> 2; return static_cast<Dot14>(x * Dot14_ONE); } static float SkUnitCubicInterp(float value, float bx, float by, float cx, float cy) { // pin to the unit-square, and convert to 2.14 Dot14 x = pin_and_convert(value); if (x == 0) return 0; if (x == Dot14_ONE) return SK_Scalar1; if (x == 0) return 0.0f; if (x == Dot14_ONE) return 1.0f; Dot14 b = pin_and_convert(bx); Dot14 c = pin_and_convert(cx); Loading Loading @@ -84,7 +83,7 @@ static float SkUnitCubicInterp(float value, float bx, float by, float cx, float A = 3 * b; B = 3 * (c - 2 * b); C = 3 * (b - c) + Dot14_ONE; return SkFixedToScalar(eval_cubic(t, A, B, C) << 2); return Dot14ToFloat(eval_cubic(t, A, B, C)); } /////////////////////////////////////////////////////////////////////////////////////////////////// Loading @@ -104,7 +103,7 @@ void SkiaInterpolatorBase::reset(int elemCount, int frameCount) { fFlags = 0; fElemCount = static_cast<uint8_t>(elemCount); fFrameCount = static_cast<int16_t>(frameCount); fRepeat = SK_Scalar1; fRepeat = 1.0f; if (fStorage) { free(fStorage); fStorage = nullptr; Loading Loading @@ -136,17 +135,46 @@ bool SkiaInterpolatorBase::getDuration(SkMSec* startTime, SkMSec* endTime) const float SkiaInterpolatorBase::ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime, const float blend[4]) { SkASSERT(time > prevTime && time < nextTime); LOG_FATAL_IF(time < prevTime || time > nextTime); float t = (float)(time - prevTime) / (float)(nextTime - prevTime); return blend ? SkUnitCubicInterp(t, blend[0], blend[1], blend[2], blend[3]) : t; } // Returns the index of where the item is or the bit not of the index // where the item should go in order to keep arr sorted in ascending order. int SkiaInterpolatorBase::binarySearch(const SkTimeCode* arr, int count, SkMSec target) { if (count <= 0) { return ~0; } int lo = 0; int hi = count - 1; while (lo < hi) { int mid = (hi + lo) / 2; SkMSec elem = arr[mid].fTime; if (elem == target) { return mid; } else if (elem < target) { lo = mid + 1; } else { hi = mid; } } // Check to see if target is greater or less than where we stopped if (target < arr[lo].fTime) { return ~lo; } // e.g. it should go at the end. return ~(lo + 1); } SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T, int* indexPtr, bool* exactPtr) const { SkASSERT(fFrameCount > 0); LOG_FATAL_IF(fFrameCount <= 0); Result result = kNormal_Result; if (fRepeat != SK_Scalar1) { if (fRepeat != 1.0f) { SkMSec startTime = 0, endTime = 0; // initialize to avoid warning this->getDuration(&startTime, &endTime); SkMSec totalTime = endTime - startTime; Loading @@ -168,10 +196,8 @@ SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T time = offsetTime + startTime; } int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time, sizeof(SkTimeCode)); int index = SkiaInterpolatorBase::binarySearch(fTimes, fFrameCount, time); bool exact = true; if (index < 0) { index = ~index; if (index == 0) { Loading @@ -184,10 +210,11 @@ SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T } result = kFreezeEnd_Result; } else { // Need to interpolate between two frames. exact = false; } } SkASSERT(index < fFrameCount); LOG_FATAL_IF(index >= fFrameCount); const SkTimeCode* nextTime = &fTimes[index]; SkMSec nextT = nextTime[0].fTime; if (exact) { Loading @@ -207,7 +234,7 @@ SkiaInterpolator::SkiaInterpolator() { } SkiaInterpolator::SkiaInterpolator(int elemCount, int frameCount) { SkASSERT(elemCount > 0); LOG_FATAL_IF(elemCount <= 0); this->reset(elemCount, frameCount); } Loading @@ -221,21 +248,19 @@ void SkiaInterpolator::reset(int elemCount, int frameCount) { fValues = (float*)((char*)fStorage + sizeof(SkTimeCode) * frameCount); } #define SK_Fixed1Third (SK_Fixed1 / 3) #define SK_Fixed2Third (SK_Fixed1 * 2 / 3) static const float gIdentityBlend[4] = {0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f}; bool SkiaInterpolator::setKeyFrame(int index, SkMSec time, const float values[], const float blend[4]) { SkASSERT(values != nullptr); LOG_FATAL_IF(values == nullptr); if (blend == nullptr) { blend = gIdentityBlend; } bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, sizeof(SkTimeCode)); SkASSERT(success); // Verify the time should go after all the frames before index bool success = ~index == SkiaInterpolatorBase::binarySearch(fTimes, index, time); LOG_FATAL_IF(!success); if (success) { SkTimeCode* timeCode = &fTimes[index]; timeCode->fTime = time; Loading @@ -257,7 +282,7 @@ SkiaInterpolator::Result SkiaInterpolator::timeToValues(SkMSec time, float value if (exact) { memcpy(values, nextSrc, fElemCount * sizeof(float)); } else { SkASSERT(index > 0); LOG_FATAL_IF(index <= 0); const float* prevSrc = nextSrc - fElemCount; Loading libs/hwui/SkiaInterpolator.h +6 −4 Original line number Diff line number Diff line Loading @@ -68,14 +68,16 @@ protected: enum Flags { kMirror = 1, kReset = 2, kHasBlend = 4 }; static float ComputeRelativeT(uint32_t time, uint32_t prevTime, uint32_t nextTime, const float blend[4] = nullptr); int16_t fFrameCount; uint8_t fElemCount; uint8_t fFlags; float fRepeat; struct SkTimeCode { uint32_t fTime; float fBlend[4]; }; static int binarySearch(const SkTimeCode* arr, int count, uint32_t target); int16_t fFrameCount; uint8_t fElemCount; uint8_t fFlags; float fRepeat; SkTimeCode* fTimes; // pointer into fStorage void* fStorage; }; Loading Loading
libs/hwui/SkiaInterpolator.cpp +48 −23 Original line number Diff line number Diff line Loading @@ -18,9 +18,8 @@ #include "include/core/SkScalar.h" #include "include/core/SkTypes.h" #include "include/private/SkFixed.h" #include "src/core/SkTSearch.h" #include <cstdlib> #include <log/log.h> typedef int Dot14; Loading @@ -41,18 +40,18 @@ static inline Dot14 pin_and_convert(float x) { if (x <= 0) { return 0; } if (x >= SK_Scalar1) { if (x >= 1.0f) { return Dot14_ONE; } return SkScalarToFixed(x) >> 2; return static_cast<Dot14>(x * Dot14_ONE); } static float SkUnitCubicInterp(float value, float bx, float by, float cx, float cy) { // pin to the unit-square, and convert to 2.14 Dot14 x = pin_and_convert(value); if (x == 0) return 0; if (x == Dot14_ONE) return SK_Scalar1; if (x == 0) return 0.0f; if (x == Dot14_ONE) return 1.0f; Dot14 b = pin_and_convert(bx); Dot14 c = pin_and_convert(cx); Loading Loading @@ -84,7 +83,7 @@ static float SkUnitCubicInterp(float value, float bx, float by, float cx, float A = 3 * b; B = 3 * (c - 2 * b); C = 3 * (b - c) + Dot14_ONE; return SkFixedToScalar(eval_cubic(t, A, B, C) << 2); return Dot14ToFloat(eval_cubic(t, A, B, C)); } /////////////////////////////////////////////////////////////////////////////////////////////////// Loading @@ -104,7 +103,7 @@ void SkiaInterpolatorBase::reset(int elemCount, int frameCount) { fFlags = 0; fElemCount = static_cast<uint8_t>(elemCount); fFrameCount = static_cast<int16_t>(frameCount); fRepeat = SK_Scalar1; fRepeat = 1.0f; if (fStorage) { free(fStorage); fStorage = nullptr; Loading Loading @@ -136,17 +135,46 @@ bool SkiaInterpolatorBase::getDuration(SkMSec* startTime, SkMSec* endTime) const float SkiaInterpolatorBase::ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime, const float blend[4]) { SkASSERT(time > prevTime && time < nextTime); LOG_FATAL_IF(time < prevTime || time > nextTime); float t = (float)(time - prevTime) / (float)(nextTime - prevTime); return blend ? SkUnitCubicInterp(t, blend[0], blend[1], blend[2], blend[3]) : t; } // Returns the index of where the item is or the bit not of the index // where the item should go in order to keep arr sorted in ascending order. int SkiaInterpolatorBase::binarySearch(const SkTimeCode* arr, int count, SkMSec target) { if (count <= 0) { return ~0; } int lo = 0; int hi = count - 1; while (lo < hi) { int mid = (hi + lo) / 2; SkMSec elem = arr[mid].fTime; if (elem == target) { return mid; } else if (elem < target) { lo = mid + 1; } else { hi = mid; } } // Check to see if target is greater or less than where we stopped if (target < arr[lo].fTime) { return ~lo; } // e.g. it should go at the end. return ~(lo + 1); } SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T, int* indexPtr, bool* exactPtr) const { SkASSERT(fFrameCount > 0); LOG_FATAL_IF(fFrameCount <= 0); Result result = kNormal_Result; if (fRepeat != SK_Scalar1) { if (fRepeat != 1.0f) { SkMSec startTime = 0, endTime = 0; // initialize to avoid warning this->getDuration(&startTime, &endTime); SkMSec totalTime = endTime - startTime; Loading @@ -168,10 +196,8 @@ SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T time = offsetTime + startTime; } int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time, sizeof(SkTimeCode)); int index = SkiaInterpolatorBase::binarySearch(fTimes, fFrameCount, time); bool exact = true; if (index < 0) { index = ~index; if (index == 0) { Loading @@ -184,10 +210,11 @@ SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T } result = kFreezeEnd_Result; } else { // Need to interpolate between two frames. exact = false; } } SkASSERT(index < fFrameCount); LOG_FATAL_IF(index >= fFrameCount); const SkTimeCode* nextTime = &fTimes[index]; SkMSec nextT = nextTime[0].fTime; if (exact) { Loading @@ -207,7 +234,7 @@ SkiaInterpolator::SkiaInterpolator() { } SkiaInterpolator::SkiaInterpolator(int elemCount, int frameCount) { SkASSERT(elemCount > 0); LOG_FATAL_IF(elemCount <= 0); this->reset(elemCount, frameCount); } Loading @@ -221,21 +248,19 @@ void SkiaInterpolator::reset(int elemCount, int frameCount) { fValues = (float*)((char*)fStorage + sizeof(SkTimeCode) * frameCount); } #define SK_Fixed1Third (SK_Fixed1 / 3) #define SK_Fixed2Third (SK_Fixed1 * 2 / 3) static const float gIdentityBlend[4] = {0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f}; bool SkiaInterpolator::setKeyFrame(int index, SkMSec time, const float values[], const float blend[4]) { SkASSERT(values != nullptr); LOG_FATAL_IF(values == nullptr); if (blend == nullptr) { blend = gIdentityBlend; } bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, sizeof(SkTimeCode)); SkASSERT(success); // Verify the time should go after all the frames before index bool success = ~index == SkiaInterpolatorBase::binarySearch(fTimes, index, time); LOG_FATAL_IF(!success); if (success) { SkTimeCode* timeCode = &fTimes[index]; timeCode->fTime = time; Loading @@ -257,7 +282,7 @@ SkiaInterpolator::Result SkiaInterpolator::timeToValues(SkMSec time, float value if (exact) { memcpy(values, nextSrc, fElemCount * sizeof(float)); } else { SkASSERT(index > 0); LOG_FATAL_IF(index <= 0); const float* prevSrc = nextSrc - fElemCount; Loading
libs/hwui/SkiaInterpolator.h +6 −4 Original line number Diff line number Diff line Loading @@ -68,14 +68,16 @@ protected: enum Flags { kMirror = 1, kReset = 2, kHasBlend = 4 }; static float ComputeRelativeT(uint32_t time, uint32_t prevTime, uint32_t nextTime, const float blend[4] = nullptr); int16_t fFrameCount; uint8_t fElemCount; uint8_t fFlags; float fRepeat; struct SkTimeCode { uint32_t fTime; float fBlend[4]; }; static int binarySearch(const SkTimeCode* arr, int count, uint32_t target); int16_t fFrameCount; uint8_t fElemCount; uint8_t fFlags; float fRepeat; SkTimeCode* fTimes; // pointer into fStorage void* fStorage; }; Loading