| Index: src/core/SkMipMap.cpp
|
| diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp
|
| index 6e921c7942d98f596c193052a5d308ff9dee06c8..eba50bcb4d2a10f11dcd8cb910289505533a8ed6 100644
|
| --- a/src/core/SkMipMap.cpp
|
| +++ b/src/core/SkMipMap.cpp
|
| @@ -383,66 +383,95 @@ template <typename T> T add_121(T a, T b, T c) {
|
| // we need to sample in each dimension to produce 1 dst pixel.
|
| //
|
|
|
| -template <typename F> void downsample_2_2(void* dst, const void* src, size_t srcRB) {
|
| +template <typename F> void downsample_2_2(void* dst, const void* src, size_t srcRB, int count) {
|
| auto p0 = static_cast<const typename F::Type*>(src);
|
| auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
|
| + auto d = static_cast<typename F::Type*>(dst);
|
|
|
| - auto c00 = F::Expand(p0[0]);
|
| - auto c01 = F::Expand(p0[1]);
|
| - auto c10 = F::Expand(p1[0]);
|
| - auto c11 = F::Expand(p1[1]);
|
| + for (int i = 0; i < count; ++i) {
|
| + auto c00 = F::Expand(p0[0]);
|
| + auto c01 = F::Expand(p0[1]);
|
| + auto c10 = F::Expand(p1[0]);
|
| + auto c11 = F::Expand(p1[1]);
|
|
|
| - auto c = c00 + c10 + c01 + c11;
|
| - *(typename F::Type*)dst = F::Compact(c >> 2);
|
| + auto c = c00 + c10 + c01 + c11;
|
| + d[i] = F::Compact(c >> 2);
|
| + p0 += 2;
|
| + p1 += 2;
|
| + }
|
| }
|
|
|
| -template <typename F> void downsample_3_2(void* dst, const void* src, size_t srcRB) {
|
| +template <typename F> void downsample_3_2(void* dst, const void* src, size_t srcRB, int count) {
|
| + SkASSERT(count > 0);
|
| auto p0 = static_cast<const typename F::Type*>(src);
|
| auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
|
| -
|
| - auto c00 = F::Expand(p0[0]);
|
| - auto c01 = F::Expand(p0[1]);
|
| - auto c02 = F::Expand(p0[2]);
|
| - auto c10 = F::Expand(p1[0]);
|
| - auto c11 = F::Expand(p1[1]);
|
| - auto c12 = F::Expand(p1[2]);
|
| -
|
| - auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12);
|
| - *(typename F::Type*)dst = F::Compact(c >> 3);
|
| + auto d = static_cast<typename F::Type*>(dst);
|
| +
|
| + auto c02 = F::Expand(p0[0]);
|
| + auto c12 = F::Expand(p1[0]);
|
| + for (int i = 0; i < count; ++i) {
|
| + auto c00 = c02;
|
| + auto c01 = F::Expand(p0[1]);
|
| + c02 = F::Expand(p0[2]);
|
| + auto c10 = c12;
|
| + auto c11 = F::Expand(p1[1]);
|
| + c12 = F::Expand(p1[2]);
|
| +
|
| + auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12);
|
| + d[i] = F::Compact(c >> 3);
|
| + p0 += 2;
|
| + p1 += 2;
|
| + }
|
| }
|
|
|
| -template <typename F> void downsample_2_3(void* dst, const void* src, size_t srcRB) {
|
| +template <typename F> void downsample_2_3(void* dst, const void* src, size_t srcRB, int count) {
|
| auto p0 = static_cast<const typename F::Type*>(src);
|
| auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
|
| auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
|
| -
|
| - auto c00 = F::Expand(p0[0]);
|
| - auto c01 = F::Expand(p0[1]);
|
| - auto c10 = F::Expand(p1[0]);
|
| - auto c11 = F::Expand(p1[1]);
|
| - auto c20 = F::Expand(p2[0]);
|
| - auto c21 = F::Expand(p2[1]);
|
| - auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21);
|
| - *(typename F::Type*)dst = F::Compact(c >> 3);
|
| + auto d = static_cast<typename F::Type*>(dst);
|
| +
|
| + for (int i = 0; i < count; ++i) {
|
| + auto c00 = F::Expand(p0[0]);
|
| + auto c01 = F::Expand(p0[1]);
|
| + auto c10 = F::Expand(p1[0]);
|
| + auto c11 = F::Expand(p1[1]);
|
| + auto c20 = F::Expand(p2[0]);
|
| + auto c21 = F::Expand(p2[1]);
|
| +
|
| + auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21);
|
| + d[i] = F::Compact(c >> 3);
|
| + p0 += 2;
|
| + p1 += 2;
|
| + p2 += 2;
|
| + }
|
| }
|
|
|
| -template <typename F> void downsample_3_3(void* dst, const void* src, size_t srcRB) {
|
| +template <typename F> void downsample_3_3(void* dst, const void* src, size_t srcRB, int count) {
|
| auto p0 = static_cast<const typename F::Type*>(src);
|
| auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
|
| auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
|
| -
|
| - auto c00 = F::Expand(p0[0]);
|
| - auto c01 = F::Expand(p0[1]);
|
| - auto c02 = F::Expand(p0[2]);
|
| - auto c10 = F::Expand(p1[0]);
|
| - auto c11 = F::Expand(p1[1]);
|
| - auto c12 = F::Expand(p1[2]);
|
| - auto c20 = F::Expand(p2[0]);
|
| - auto c21 = F::Expand(p2[1]);
|
| - auto c22 = F::Expand(p2[2]);
|
| -
|
| - auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_121(c20, c21, c22);
|
| - *(typename F::Type*)dst = F::Compact(c >> 4);
|
| + auto d = static_cast<typename F::Type*>(dst);
|
| +
|
| + auto c02 = F::Expand(p0[0]);
|
| + auto c12 = F::Expand(p1[0]);
|
| + auto c22 = F::Expand(p2[0]);
|
| + for (int i = 0; i < count; ++i) {
|
| + auto c00 = c02;
|
| + auto c01 = F::Expand(p0[1]);
|
| + c02 = F::Expand(p0[2]);
|
| + auto c10 = c12;
|
| + auto c11 = F::Expand(p1[1]);
|
| + c12 = F::Expand(p1[2]);
|
| + auto c20 = c22;
|
| + auto c21 = F::Expand(p2[1]);
|
| + c22 = F::Expand(p2[2]);
|
| +
|
| + auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_121(c20, c21, c22);
|
| + d[i] = F::Compact(c >> 4);
|
| + p0 += 2;
|
| + p1 += 2;
|
| + p2 += 2;
|
| + }
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
| @@ -459,7 +488,7 @@ size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) {
|
| }
|
|
|
| SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) {
|
| - typedef void FilterProc(void*, const void* srcPtr, size_t srcRB);
|
| + typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count);
|
|
|
| FilterProc* proc_2_2 = nullptr;
|
| FilterProc* proc_2_3 = nullptr;
|
| @@ -559,9 +588,21 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) {
|
| uint32_t rowBytes;
|
| SkPixmap srcPM(srcPixmap);
|
|
|
| - int prevW = width;
|
| - int prevH = height;
|
| for (int i = 0; i < countLevels; ++i) {
|
| + FilterProc* proc;
|
| + if (height & 1) { // src-height is 3
|
| + if (width & 1) { // src-width is 3
|
| + proc = proc_3_3;
|
| + } else { // src-width is 2
|
| + proc = proc_2_3;
|
| + }
|
| + } else { // src-height is 2
|
| + if (width & 1) { // src-width is 3
|
| + proc = proc_3_2;
|
| + } else { // src-width is 2
|
| + proc = proc_2_2;
|
| + }
|
| + }
|
| width >>= 1;
|
| height >>= 1;
|
| rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width));
|
| @@ -574,44 +615,17 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) {
|
|
|
| SkPixmap dstPM(SkImageInfo::Make(width, height, ct, at), addr, rowBytes);
|
|
|
| - const size_t pixelSize = srcPM.info().bytesPerPixel();
|
| -
|
| const void* srcBasePtr = srcPM.addr();
|
| void* dstBasePtr = dstPM.writable_addr();
|
|
|
| - FilterProc* proc;
|
| - if (prevH & 1) { // src-height is 3
|
| - if (prevW & 1) { // src-width is 3
|
| - proc = proc_3_3;
|
| - } else { // src-width is 2
|
| - proc = proc_2_3;
|
| - }
|
| - } else { // src-height is 2
|
| - if (prevW & 1) { // src-width is 3
|
| - proc = proc_3_2;
|
| - } else { // src-width is 2
|
| - proc = proc_2_2;
|
| - }
|
| - }
|
| -
|
| const size_t srcRB = srcPM.rowBytes();
|
| for (int y = 0; y < height; y++) {
|
| - const void* srcPtr = srcBasePtr;
|
| - void* dstPtr = dstBasePtr;
|
| -
|
| - for (int x = 0; x < width; x++) {
|
| - proc(dstPtr, srcPtr, srcRB);
|
| - srcPtr = (char*)srcPtr + pixelSize * 2;
|
| - dstPtr = (char*)dstPtr + pixelSize;
|
| - }
|
| -
|
| + proc(dstBasePtr, srcBasePtr, srcRB, width);
|
| srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows
|
| dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes();
|
| }
|
| srcPM = dstPM;
|
| addr += height * rowBytes;
|
| - prevW = width;
|
| - prevH = height;
|
| }
|
| SkASSERT(addr == baseAddr + size);
|
|
|
|
|