1dc6c8babf04fe6c19087d441896a3d49f3322cc7reed@google.com/* 2dc6c8babf04fe6c19087d441896a3d49f3322cc7reed@google.com * Copyright 2013 Google Inc. 3dc6c8babf04fe6c19087d441896a3d49f3322cc7reed@google.com * 4dc6c8babf04fe6c19087d441896a3d49f3322cc7reed@google.com * Use of this source code is governed by a BSD-style license that can be 5dc6c8babf04fe6c19087d441896a3d49f3322cc7reed@google.com * found in the LICENSE file. 6dc6c8babf04fe6c19087d441896a3d49f3322cc7reed@google.com */ 7dc6c8babf04fe6c19087d441896a3d49f3322cc7reed@google.com 8eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com#include "SkMipMap.h" 9eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com#include "SkBitmap.h" 10eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com#include "SkColorPriv.h" 11e2412d5738e4ee37a897cc51996431a4dfb10436cblume#include "SkMath.h" 12550e9b0ef1c0fba42e2e902a467af322ad2413damtklein#include "SkNx.h" 13e2412d5738e4ee37a897cc51996431a4dfb10436cblume#include "SkTypes.h" 14eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com 1532e0b4a34a2d461927056677e0ef99241e29df0dreed// 1632e0b4a34a2d461927056677e0ef99241e29df0dreed// ColorTypeFilter is the "Type" we pass to some downsample template functions. 1732e0b4a34a2d461927056677e0ef99241e29df0dreed// It controls how we expand a pixel into a large type, with space between each component, 1832e0b4a34a2d461927056677e0ef99241e29df0dreed// so we can then perform our simple filter (either box or triangle) and store the intermediates 1932e0b4a34a2d461927056677e0ef99241e29df0dreed// in the expanded type. 2032e0b4a34a2d461927056677e0ef99241e29df0dreed// 2132e0b4a34a2d461927056677e0ef99241e29df0dreed 2232e0b4a34a2d461927056677e0ef99241e29df0dreedstruct ColorTypeFilter_8888 { 2332e0b4a34a2d461927056677e0ef99241e29df0dreed typedef uint32_t Type; 24550e9b0ef1c0fba42e2e902a467af322ad2413damtklein#if defined(SKNX_IS_FAST) 25550e9b0ef1c0fba42e2e902a467af322ad2413damtklein static Sk4h Expand(uint32_t x) { 26507ef6d68115ae9e6d884bb36436a1463523d893mtklein return SkNx_cast<uint16_t>(Sk4b::Load(&x)); 27550e9b0ef1c0fba42e2e902a467af322ad2413damtklein } 28550e9b0ef1c0fba42e2e902a467af322ad2413damtklein static uint32_t Compact(const Sk4h& x) { 29550e9b0ef1c0fba42e2e902a467af322ad2413damtklein uint32_t r; 30507ef6d68115ae9e6d884bb36436a1463523d893mtklein SkNx_cast<uint8_t>(x).store(&r); 31550e9b0ef1c0fba42e2e902a467af322ad2413damtklein return r; 32550e9b0ef1c0fba42e2e902a467af322ad2413damtklein } 33550e9b0ef1c0fba42e2e902a467af322ad2413damtklein#else 3432e0b4a34a2d461927056677e0ef99241e29df0dreed static uint64_t Expand(uint32_t x) { 3532e0b4a34a2d461927056677e0ef99241e29df0dreed return (x & 0xFF00FF) | ((uint64_t)(x & 0xFF00FF00) << 24); 3632e0b4a34a2d461927056677e0ef99241e29df0dreed } 3732e0b4a34a2d461927056677e0ef99241e29df0dreed static uint32_t Compact(uint64_t x) { 3832e0b4a34a2d461927056677e0ef99241e29df0dreed return (uint32_t)((x & 0xFF00FF) | ((x >> 24) & 0xFF00FF00)); 3932e0b4a34a2d461927056677e0ef99241e29df0dreed } 40550e9b0ef1c0fba42e2e902a467af322ad2413damtklein#endif 4132e0b4a34a2d461927056677e0ef99241e29df0dreed}; 4232e0b4a34a2d461927056677e0ef99241e29df0dreed 4332e0b4a34a2d461927056677e0ef99241e29df0dreedstruct ColorTypeFilter_565 { 4432e0b4a34a2d461927056677e0ef99241e29df0dreed typedef uint16_t Type; 4532e0b4a34a2d461927056677e0ef99241e29df0dreed static uint32_t Expand(uint16_t x) { 4632e0b4a34a2d461927056677e0ef99241e29df0dreed return (x & ~SK_G16_MASK_IN_PLACE) | ((x & SK_G16_MASK_IN_PLACE) << 16); 4732e0b4a34a2d461927056677e0ef99241e29df0dreed } 4832e0b4a34a2d461927056677e0ef99241e29df0dreed static uint16_t Compact(uint32_t x) { 4932e0b4a34a2d461927056677e0ef99241e29df0dreed return (x & ~SK_G16_MASK_IN_PLACE) | ((x >> 16) & SK_G16_MASK_IN_PLACE); 5032e0b4a34a2d461927056677e0ef99241e29df0dreed } 5132e0b4a34a2d461927056677e0ef99241e29df0dreed}; 5232e0b4a34a2d461927056677e0ef99241e29df0dreed 5332e0b4a34a2d461927056677e0ef99241e29df0dreedstruct ColorTypeFilter_4444 { 5432e0b4a34a2d461927056677e0ef99241e29df0dreed typedef uint16_t Type; 5532e0b4a34a2d461927056677e0ef99241e29df0dreed static uint32_t Expand(uint16_t x) { 5632e0b4a34a2d461927056677e0ef99241e29df0dreed return (x & 0xF0F) | ((x & ~0xF0F) << 12); 5732e0b4a34a2d461927056677e0ef99241e29df0dreed } 5832e0b4a34a2d461927056677e0ef99241e29df0dreed static uint16_t Compact(uint32_t x) { 5932e0b4a34a2d461927056677e0ef99241e29df0dreed return (x & 0xF0F) | ((x >> 12) & ~0xF0F); 6032e0b4a34a2d461927056677e0ef99241e29df0dreed } 6132e0b4a34a2d461927056677e0ef99241e29df0dreed}; 6232e0b4a34a2d461927056677e0ef99241e29df0dreed 6332e0b4a34a2d461927056677e0ef99241e29df0dreedstruct ColorTypeFilter_8 { 6432e0b4a34a2d461927056677e0ef99241e29df0dreed typedef uint8_t Type; 6532e0b4a34a2d461927056677e0ef99241e29df0dreed static unsigned Expand(unsigned x) { 6632e0b4a34a2d461927056677e0ef99241e29df0dreed return x; 6732e0b4a34a2d461927056677e0ef99241e29df0dreed } 6832e0b4a34a2d461927056677e0ef99241e29df0dreed static uint8_t Compact(unsigned x) { 6932e0b4a34a2d461927056677e0ef99241e29df0dreed return (uint8_t)x; 7032e0b4a34a2d461927056677e0ef99241e29df0dreed } 7132e0b4a34a2d461927056677e0ef99241e29df0dreed}; 7232e0b4a34a2d461927056677e0ef99241e29df0dreed 73550e9b0ef1c0fba42e2e902a467af322ad2413damtkleintemplate <typename T> T add_121(const T& a, const T& b, const T& c) { 7432e0b4a34a2d461927056677e0ef99241e29df0dreed return a + b + b + c; 7532e0b4a34a2d461927056677e0ef99241e29df0dreed} 7632e0b4a34a2d461927056677e0ef99241e29df0dreed 7732e0b4a34a2d461927056677e0ef99241e29df0dreed// 7832e0b4a34a2d461927056677e0ef99241e29df0dreed// To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50,50) 7932e0b4a34a2d461927056677e0ef99241e29df0dreed// If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50) 8032e0b4a34a2d461927056677e0ef99241e29df0dreed// In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings, 8132e0b4a34a2d461927056677e0ef99241e29df0dreed// else for even cases, we just use a 2x box filter. 8232e0b4a34a2d461927056677e0ef99241e29df0dreed// 8332e0b4a34a2d461927056677e0ef99241e29df0dreed// This produces 4 possible filters: 2x2 2x3 3x2 3x3 where WxH indicates the number of src pixels 8432e0b4a34a2d461927056677e0ef99241e29df0dreed// we need to sample in each dimension to produce 1 dst pixel. 8532e0b4a34a2d461927056677e0ef99241e29df0dreed// 8632e0b4a34a2d461927056677e0ef99241e29df0dreed 87326253ef22d39e72a729e8069e54b34ade72ad1breedtemplate <typename F> void downsample_2_2(void* dst, const void* src, size_t srcRB, int count) { 8832e0b4a34a2d461927056677e0ef99241e29df0dreed auto p0 = static_cast<const typename F::Type*>(src); 8932e0b4a34a2d461927056677e0ef99241e29df0dreed auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 90326253ef22d39e72a729e8069e54b34ade72ad1breed auto d = static_cast<typename F::Type*>(dst); 9132e0b4a34a2d461927056677e0ef99241e29df0dreed 92326253ef22d39e72a729e8069e54b34ade72ad1breed for (int i = 0; i < count; ++i) { 93326253ef22d39e72a729e8069e54b34ade72ad1breed auto c00 = F::Expand(p0[0]); 94326253ef22d39e72a729e8069e54b34ade72ad1breed auto c01 = F::Expand(p0[1]); 95326253ef22d39e72a729e8069e54b34ade72ad1breed auto c10 = F::Expand(p1[0]); 96326253ef22d39e72a729e8069e54b34ade72ad1breed auto c11 = F::Expand(p1[1]); 9732e0b4a34a2d461927056677e0ef99241e29df0dreed 98326253ef22d39e72a729e8069e54b34ade72ad1breed auto c = c00 + c10 + c01 + c11; 99326253ef22d39e72a729e8069e54b34ade72ad1breed d[i] = F::Compact(c >> 2); 100326253ef22d39e72a729e8069e54b34ade72ad1breed p0 += 2; 101326253ef22d39e72a729e8069e54b34ade72ad1breed p1 += 2; 102326253ef22d39e72a729e8069e54b34ade72ad1breed } 10332e0b4a34a2d461927056677e0ef99241e29df0dreed} 10432e0b4a34a2d461927056677e0ef99241e29df0dreed 105326253ef22d39e72a729e8069e54b34ade72ad1breedtemplate <typename F> void downsample_3_2(void* dst, const void* src, size_t srcRB, int count) { 106326253ef22d39e72a729e8069e54b34ade72ad1breed SkASSERT(count > 0); 10732e0b4a34a2d461927056677e0ef99241e29df0dreed auto p0 = static_cast<const typename F::Type*>(src); 10832e0b4a34a2d461927056677e0ef99241e29df0dreed auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 109326253ef22d39e72a729e8069e54b34ade72ad1breed auto d = static_cast<typename F::Type*>(dst); 110550e9b0ef1c0fba42e2e902a467af322ad2413damtklein 111326253ef22d39e72a729e8069e54b34ade72ad1breed auto c02 = F::Expand(p0[0]); 112326253ef22d39e72a729e8069e54b34ade72ad1breed auto c12 = F::Expand(p1[0]); 113326253ef22d39e72a729e8069e54b34ade72ad1breed for (int i = 0; i < count; ++i) { 114326253ef22d39e72a729e8069e54b34ade72ad1breed auto c00 = c02; 115326253ef22d39e72a729e8069e54b34ade72ad1breed auto c01 = F::Expand(p0[1]); 116326253ef22d39e72a729e8069e54b34ade72ad1breed c02 = F::Expand(p0[2]); 117326253ef22d39e72a729e8069e54b34ade72ad1breed auto c10 = c12; 118326253ef22d39e72a729e8069e54b34ade72ad1breed auto c11 = F::Expand(p1[1]); 119326253ef22d39e72a729e8069e54b34ade72ad1breed c12 = F::Expand(p1[2]); 120326253ef22d39e72a729e8069e54b34ade72ad1breed 121326253ef22d39e72a729e8069e54b34ade72ad1breed auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12); 122326253ef22d39e72a729e8069e54b34ade72ad1breed d[i] = F::Compact(c >> 3); 123326253ef22d39e72a729e8069e54b34ade72ad1breed p0 += 2; 124326253ef22d39e72a729e8069e54b34ade72ad1breed p1 += 2; 125326253ef22d39e72a729e8069e54b34ade72ad1breed } 12632e0b4a34a2d461927056677e0ef99241e29df0dreed} 12732e0b4a34a2d461927056677e0ef99241e29df0dreed 128326253ef22d39e72a729e8069e54b34ade72ad1breedtemplate <typename F> void downsample_2_3(void* dst, const void* src, size_t srcRB, int count) { 12932e0b4a34a2d461927056677e0ef99241e29df0dreed auto p0 = static_cast<const typename F::Type*>(src); 13032e0b4a34a2d461927056677e0ef99241e29df0dreed auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 13132e0b4a34a2d461927056677e0ef99241e29df0dreed auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 132326253ef22d39e72a729e8069e54b34ade72ad1breed auto d = static_cast<typename F::Type*>(dst); 133550e9b0ef1c0fba42e2e902a467af322ad2413damtklein 134326253ef22d39e72a729e8069e54b34ade72ad1breed for (int i = 0; i < count; ++i) { 135326253ef22d39e72a729e8069e54b34ade72ad1breed auto c00 = F::Expand(p0[0]); 136326253ef22d39e72a729e8069e54b34ade72ad1breed auto c01 = F::Expand(p0[1]); 137326253ef22d39e72a729e8069e54b34ade72ad1breed auto c10 = F::Expand(p1[0]); 138326253ef22d39e72a729e8069e54b34ade72ad1breed auto c11 = F::Expand(p1[1]); 139326253ef22d39e72a729e8069e54b34ade72ad1breed auto c20 = F::Expand(p2[0]); 140326253ef22d39e72a729e8069e54b34ade72ad1breed auto c21 = F::Expand(p2[1]); 141326253ef22d39e72a729e8069e54b34ade72ad1breed 142326253ef22d39e72a729e8069e54b34ade72ad1breed auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21); 143326253ef22d39e72a729e8069e54b34ade72ad1breed d[i] = F::Compact(c >> 3); 144326253ef22d39e72a729e8069e54b34ade72ad1breed p0 += 2; 145326253ef22d39e72a729e8069e54b34ade72ad1breed p1 += 2; 146326253ef22d39e72a729e8069e54b34ade72ad1breed p2 += 2; 147326253ef22d39e72a729e8069e54b34ade72ad1breed } 14832e0b4a34a2d461927056677e0ef99241e29df0dreed} 14932e0b4a34a2d461927056677e0ef99241e29df0dreed 150326253ef22d39e72a729e8069e54b34ade72ad1breedtemplate <typename F> void downsample_3_3(void* dst, const void* src, size_t srcRB, int count) { 15132e0b4a34a2d461927056677e0ef99241e29df0dreed auto p0 = static_cast<const typename F::Type*>(src); 15232e0b4a34a2d461927056677e0ef99241e29df0dreed auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 15332e0b4a34a2d461927056677e0ef99241e29df0dreed auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 154326253ef22d39e72a729e8069e54b34ade72ad1breed auto d = static_cast<typename F::Type*>(dst); 155326253ef22d39e72a729e8069e54b34ade72ad1breed 156326253ef22d39e72a729e8069e54b34ade72ad1breed auto c02 = F::Expand(p0[0]); 157326253ef22d39e72a729e8069e54b34ade72ad1breed auto c12 = F::Expand(p1[0]); 158326253ef22d39e72a729e8069e54b34ade72ad1breed auto c22 = F::Expand(p2[0]); 159326253ef22d39e72a729e8069e54b34ade72ad1breed for (int i = 0; i < count; ++i) { 160326253ef22d39e72a729e8069e54b34ade72ad1breed auto c00 = c02; 161326253ef22d39e72a729e8069e54b34ade72ad1breed auto c01 = F::Expand(p0[1]); 162326253ef22d39e72a729e8069e54b34ade72ad1breed c02 = F::Expand(p0[2]); 163326253ef22d39e72a729e8069e54b34ade72ad1breed auto c10 = c12; 164326253ef22d39e72a729e8069e54b34ade72ad1breed auto c11 = F::Expand(p1[1]); 165326253ef22d39e72a729e8069e54b34ade72ad1breed c12 = F::Expand(p1[2]); 166326253ef22d39e72a729e8069e54b34ade72ad1breed auto c20 = c22; 167326253ef22d39e72a729e8069e54b34ade72ad1breed auto c21 = F::Expand(p2[1]); 168326253ef22d39e72a729e8069e54b34ade72ad1breed c22 = F::Expand(p2[2]); 169326253ef22d39e72a729e8069e54b34ade72ad1breed 170326253ef22d39e72a729e8069e54b34ade72ad1breed auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_121(c20, c21, c22); 171326253ef22d39e72a729e8069e54b34ade72ad1breed d[i] = F::Compact(c >> 4); 172326253ef22d39e72a729e8069e54b34ade72ad1breed p0 += 2; 173326253ef22d39e72a729e8069e54b34ade72ad1breed p1 += 2; 174326253ef22d39e72a729e8069e54b34ade72ad1breed p2 += 2; 175326253ef22d39e72a729e8069e54b34ade72ad1breed } 17632e0b4a34a2d461927056677e0ef99241e29df0dreed} 17732e0b4a34a2d461927056677e0ef99241e29df0dreed 17832e0b4a34a2d461927056677e0ef99241e29df0dreed/////////////////////////////////////////////////////////////////////////////////////////////////// 17932e0b4a34a2d461927056677e0ef99241e29df0dreed 18032e0b4a34a2d461927056677e0ef99241e29df0dreedsize_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { 18132e0b4a34a2d461927056677e0ef99241e29df0dreed if (levelCount < 0) { 18232e0b4a34a2d461927056677e0ef99241e29df0dreed return 0; 18332e0b4a34a2d461927056677e0ef99241e29df0dreed } 18432e0b4a34a2d461927056677e0ef99241e29df0dreed int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; 18532e0b4a34a2d461927056677e0ef99241e29df0dreed if (!sk_64_isS32(size)) { 18632e0b4a34a2d461927056677e0ef99241e29df0dreed return 0; 18732e0b4a34a2d461927056677e0ef99241e29df0dreed } 18832e0b4a34a2d461927056677e0ef99241e29df0dreed return sk_64_asS32(size); 18932e0b4a34a2d461927056677e0ef99241e29df0dreed} 19032e0b4a34a2d461927056677e0ef99241e29df0dreed 19167b09bf6b7422c7a3209781cbb7827224e3ffc17reedSkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) { 192326253ef22d39e72a729e8069e54b34ade72ad1breed typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count); 19332e0b4a34a2d461927056677e0ef99241e29df0dreed 19432e0b4a34a2d461927056677e0ef99241e29df0dreed FilterProc* proc_2_2 = nullptr; 19532e0b4a34a2d461927056677e0ef99241e29df0dreed FilterProc* proc_2_3 = nullptr; 19632e0b4a34a2d461927056677e0ef99241e29df0dreed FilterProc* proc_3_2 = nullptr; 19732e0b4a34a2d461927056677e0ef99241e29df0dreed FilterProc* proc_3_3 = nullptr; 19832e0b4a34a2d461927056677e0ef99241e29df0dreed 19932e0b4a34a2d461927056677e0ef99241e29df0dreed const SkColorType ct = src.colorType(); 20032e0b4a34a2d461927056677e0ef99241e29df0dreed const SkAlphaType at = src.alphaType(); 20132e0b4a34a2d461927056677e0ef99241e29df0dreed switch (ct) { 20232e0b4a34a2d461927056677e0ef99241e29df0dreed case kRGBA_8888_SkColorType: 20332e0b4a34a2d461927056677e0ef99241e29df0dreed case kBGRA_8888_SkColorType: 20432e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_2 = downsample_2_2<ColorTypeFilter_8888>; 20532e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_3 = downsample_2_3<ColorTypeFilter_8888>; 20632e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_2 = downsample_3_2<ColorTypeFilter_8888>; 20732e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_3 = downsample_3_3<ColorTypeFilter_8888>; 20832e0b4a34a2d461927056677e0ef99241e29df0dreed break; 20932e0b4a34a2d461927056677e0ef99241e29df0dreed case kRGB_565_SkColorType: 21032e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_2 = downsample_2_2<ColorTypeFilter_565>; 21132e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_3 = downsample_2_3<ColorTypeFilter_565>; 21232e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_2 = downsample_3_2<ColorTypeFilter_565>; 21332e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_3 = downsample_3_3<ColorTypeFilter_565>; 21432e0b4a34a2d461927056677e0ef99241e29df0dreed break; 21532e0b4a34a2d461927056677e0ef99241e29df0dreed case kARGB_4444_SkColorType: 21632e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_2 = downsample_2_2<ColorTypeFilter_4444>; 21732e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_3 = downsample_2_3<ColorTypeFilter_4444>; 21832e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_2 = downsample_3_2<ColorTypeFilter_4444>; 21932e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_3 = downsample_3_3<ColorTypeFilter_4444>; 22032e0b4a34a2d461927056677e0ef99241e29df0dreed break; 22132e0b4a34a2d461927056677e0ef99241e29df0dreed case kAlpha_8_SkColorType: 22232e0b4a34a2d461927056677e0ef99241e29df0dreed case kGray_8_SkColorType: 22332e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_2 = downsample_2_2<ColorTypeFilter_8>; 22432e0b4a34a2d461927056677e0ef99241e29df0dreed proc_2_3 = downsample_2_3<ColorTypeFilter_8>; 22532e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_2 = downsample_3_2<ColorTypeFilter_8>; 22632e0b4a34a2d461927056677e0ef99241e29df0dreed proc_3_3 = downsample_3_3<ColorTypeFilter_8>; 22732e0b4a34a2d461927056677e0ef99241e29df0dreed break; 22832e0b4a34a2d461927056677e0ef99241e29df0dreed default: 22932e0b4a34a2d461927056677e0ef99241e29df0dreed // TODO: We could build miplevels for kIndex8 if the levels were in 8888. 23032e0b4a34a2d461927056677e0ef99241e29df0dreed // Means using more ram, but the quality would be fine. 23132e0b4a34a2d461927056677e0ef99241e29df0dreed return nullptr; 23232e0b4a34a2d461927056677e0ef99241e29df0dreed } 23332e0b4a34a2d461927056677e0ef99241e29df0dreed 23432e0b4a34a2d461927056677e0ef99241e29df0dreed // whip through our loop to compute the exact size needed 23532e0b4a34a2d461927056677e0ef99241e29df0dreed size_t size = 0; 23632e0b4a34a2d461927056677e0ef99241e29df0dreed int countLevels = 0; 23732e0b4a34a2d461927056677e0ef99241e29df0dreed { 23832e0b4a34a2d461927056677e0ef99241e29df0dreed int width = src.width(); 23932e0b4a34a2d461927056677e0ef99241e29df0dreed int height = src.height(); 24032e0b4a34a2d461927056677e0ef99241e29df0dreed for (;;) { 24132e0b4a34a2d461927056677e0ef99241e29df0dreed width >>= 1; 24232e0b4a34a2d461927056677e0ef99241e29df0dreed height >>= 1; 24332e0b4a34a2d461927056677e0ef99241e29df0dreed if (0 == width || 0 == height) { 24432e0b4a34a2d461927056677e0ef99241e29df0dreed break; 24532e0b4a34a2d461927056677e0ef99241e29df0dreed } 24632e0b4a34a2d461927056677e0ef99241e29df0dreed size += SkColorTypeMinRowBytes(ct, width) * height; 24732e0b4a34a2d461927056677e0ef99241e29df0dreed countLevels += 1; 24832e0b4a34a2d461927056677e0ef99241e29df0dreed } 24932e0b4a34a2d461927056677e0ef99241e29df0dreed } 25032e0b4a34a2d461927056677e0ef99241e29df0dreed if (0 == countLevels) { 25132e0b4a34a2d461927056677e0ef99241e29df0dreed return nullptr; 25232e0b4a34a2d461927056677e0ef99241e29df0dreed } 25332e0b4a34a2d461927056677e0ef99241e29df0dreed 254e2412d5738e4ee37a897cc51996431a4dfb10436cblume SkASSERT(countLevels == SkMipMap::ComputeLevelCount(src.width(), src.height())); 255e2412d5738e4ee37a897cc51996431a4dfb10436cblume 25632e0b4a34a2d461927056677e0ef99241e29df0dreed size_t storageSize = SkMipMap::AllocLevelsSize(countLevels, size); 25732e0b4a34a2d461927056677e0ef99241e29df0dreed if (0 == storageSize) { 25832e0b4a34a2d461927056677e0ef99241e29df0dreed return nullptr; 25932e0b4a34a2d461927056677e0ef99241e29df0dreed } 26032e0b4a34a2d461927056677e0ef99241e29df0dreed 26132e0b4a34a2d461927056677e0ef99241e29df0dreed SkMipMap* mipmap; 26232e0b4a34a2d461927056677e0ef99241e29df0dreed if (fact) { 26332e0b4a34a2d461927056677e0ef99241e29df0dreed SkDiscardableMemory* dm = fact(storageSize); 26432e0b4a34a2d461927056677e0ef99241e29df0dreed if (nullptr == dm) { 26532e0b4a34a2d461927056677e0ef99241e29df0dreed return nullptr; 26632e0b4a34a2d461927056677e0ef99241e29df0dreed } 26732e0b4a34a2d461927056677e0ef99241e29df0dreed mipmap = new SkMipMap(storageSize, dm); 26832e0b4a34a2d461927056677e0ef99241e29df0dreed } else { 26932e0b4a34a2d461927056677e0ef99241e29df0dreed mipmap = new SkMipMap(sk_malloc_throw(storageSize), storageSize); 27032e0b4a34a2d461927056677e0ef99241e29df0dreed } 27132e0b4a34a2d461927056677e0ef99241e29df0dreed 27232e0b4a34a2d461927056677e0ef99241e29df0dreed // init 27332e0b4a34a2d461927056677e0ef99241e29df0dreed mipmap->fCount = countLevels; 27432e0b4a34a2d461927056677e0ef99241e29df0dreed mipmap->fLevels = (Level*)mipmap->writable_data(); 27532e0b4a34a2d461927056677e0ef99241e29df0dreed 27632e0b4a34a2d461927056677e0ef99241e29df0dreed Level* levels = mipmap->fLevels; 27732e0b4a34a2d461927056677e0ef99241e29df0dreed uint8_t* baseAddr = (uint8_t*)&levels[countLevels]; 27832e0b4a34a2d461927056677e0ef99241e29df0dreed uint8_t* addr = baseAddr; 27932e0b4a34a2d461927056677e0ef99241e29df0dreed int width = src.width(); 28032e0b4a34a2d461927056677e0ef99241e29df0dreed int height = src.height(); 28132e0b4a34a2d461927056677e0ef99241e29df0dreed uint32_t rowBytes; 28267b09bf6b7422c7a3209781cbb7827224e3ffc17reed SkPixmap srcPM(src); 28332e0b4a34a2d461927056677e0ef99241e29df0dreed 28432e0b4a34a2d461927056677e0ef99241e29df0dreed for (int i = 0; i < countLevels; ++i) { 285326253ef22d39e72a729e8069e54b34ade72ad1breed FilterProc* proc; 286326253ef22d39e72a729e8069e54b34ade72ad1breed if (height & 1) { // src-height is 3 287326253ef22d39e72a729e8069e54b34ade72ad1breed if (width & 1) { // src-width is 3 288326253ef22d39e72a729e8069e54b34ade72ad1breed proc = proc_3_3; 289326253ef22d39e72a729e8069e54b34ade72ad1breed } else { // src-width is 2 290326253ef22d39e72a729e8069e54b34ade72ad1breed proc = proc_2_3; 291326253ef22d39e72a729e8069e54b34ade72ad1breed } 292326253ef22d39e72a729e8069e54b34ade72ad1breed } else { // src-height is 2 293326253ef22d39e72a729e8069e54b34ade72ad1breed if (width & 1) { // src-width is 3 294326253ef22d39e72a729e8069e54b34ade72ad1breed proc = proc_3_2; 295326253ef22d39e72a729e8069e54b34ade72ad1breed } else { // src-width is 2 296326253ef22d39e72a729e8069e54b34ade72ad1breed proc = proc_2_2; 297326253ef22d39e72a729e8069e54b34ade72ad1breed } 298326253ef22d39e72a729e8069e54b34ade72ad1breed } 29932e0b4a34a2d461927056677e0ef99241e29df0dreed width >>= 1; 30032e0b4a34a2d461927056677e0ef99241e29df0dreed height >>= 1; 30132e0b4a34a2d461927056677e0ef99241e29df0dreed rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); 30232e0b4a34a2d461927056677e0ef99241e29df0dreed 30367b09bf6b7422c7a3209781cbb7827224e3ffc17reed levels[i].fPixmap = SkPixmap(SkImageInfo::Make(width, height, ct, at), addr, rowBytes); 304921d7ac75206740e69fc6bc9893971249a909fe1fmalita levels[i].fScale = SkSize::Make(SkIntToScalar(width) / src.width(), 305921d7ac75206740e69fc6bc9893971249a909fe1fmalita SkIntToScalar(height) / src.height()); 30632e0b4a34a2d461927056677e0ef99241e29df0dreed 30767b09bf6b7422c7a3209781cbb7827224e3ffc17reed const SkPixmap& dstPM = levels[i].fPixmap; 30832e0b4a34a2d461927056677e0ef99241e29df0dreed const void* srcBasePtr = srcPM.addr(); 30932e0b4a34a2d461927056677e0ef99241e29df0dreed void* dstBasePtr = dstPM.writable_addr(); 31032e0b4a34a2d461927056677e0ef99241e29df0dreed 31132e0b4a34a2d461927056677e0ef99241e29df0dreed const size_t srcRB = srcPM.rowBytes(); 31232e0b4a34a2d461927056677e0ef99241e29df0dreed for (int y = 0; y < height; y++) { 313326253ef22d39e72a729e8069e54b34ade72ad1breed proc(dstBasePtr, srcBasePtr, srcRB, width); 31432e0b4a34a2d461927056677e0ef99241e29df0dreed srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows 31532e0b4a34a2d461927056677e0ef99241e29df0dreed dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); 31632e0b4a34a2d461927056677e0ef99241e29df0dreed } 31732e0b4a34a2d461927056677e0ef99241e29df0dreed srcPM = dstPM; 31832e0b4a34a2d461927056677e0ef99241e29df0dreed addr += height * rowBytes; 31932e0b4a34a2d461927056677e0ef99241e29df0dreed } 32032e0b4a34a2d461927056677e0ef99241e29df0dreed SkASSERT(addr == baseAddr + size); 321eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com 3229d93c2ebb31bf996905532446644f242339a774ereed return mipmap; 323d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com} 324d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com 325e2412d5738e4ee37a897cc51996431a4dfb10436cblumeint SkMipMap::ComputeLevelCount(int baseWidth, int baseHeight) { 326e2412d5738e4ee37a897cc51996431a4dfb10436cblume // OpenGL's spec requires that each mipmap level have height/width equal to 327e2412d5738e4ee37a897cc51996431a4dfb10436cblume // max(1, floor(original_height / 2^i) 328e2412d5738e4ee37a897cc51996431a4dfb10436cblume // (or original_width) where i is the mipmap level. 329e2412d5738e4ee37a897cc51996431a4dfb10436cblume // Continue scaling down until both axes are size 1. 330e2412d5738e4ee37a897cc51996431a4dfb10436cblume // 331e2412d5738e4ee37a897cc51996431a4dfb10436cblume // This means it maintains isotropic space (both axes scaling down 332e2412d5738e4ee37a897cc51996431a4dfb10436cblume // at the same rate) until one axis hits size 1. 333e2412d5738e4ee37a897cc51996431a4dfb10436cblume // At that point, OpenGL continues to scale down into anisotropic space 334e2412d5738e4ee37a897cc51996431a4dfb10436cblume // (where the scales are not the same between axes). 335e2412d5738e4ee37a897cc51996431a4dfb10436cblume // 336e2412d5738e4ee37a897cc51996431a4dfb10436cblume // Skia currently does not go into anisotropic space. 337e2412d5738e4ee37a897cc51996431a4dfb10436cblume // Once an axis hits size 1 we stop. 338e2412d5738e4ee37a897cc51996431a4dfb10436cblume // All this means is rather than use the largest axis we will use the 339e2412d5738e4ee37a897cc51996431a4dfb10436cblume // smallest axis. 340e2412d5738e4ee37a897cc51996431a4dfb10436cblume 341e2412d5738e4ee37a897cc51996431a4dfb10436cblume const int smallestAxis = SkTMin(baseWidth, baseHeight); 342e2412d5738e4ee37a897cc51996431a4dfb10436cblume if (smallestAxis < 2) { 343e2412d5738e4ee37a897cc51996431a4dfb10436cblume // SkMipMap::Build requires a minimum size of 2. 344e2412d5738e4ee37a897cc51996431a4dfb10436cblume return 0; 345e2412d5738e4ee37a897cc51996431a4dfb10436cblume } 346e2412d5738e4ee37a897cc51996431a4dfb10436cblume const int leadingZeros = SkCLZ(static_cast<uint32_t>(smallestAxis)); 347e2412d5738e4ee37a897cc51996431a4dfb10436cblume // If the value 00011010 has 3 leading 0s then it has 5 significant bits 348e2412d5738e4ee37a897cc51996431a4dfb10436cblume // (the bits which are not leading zeros) 349e2412d5738e4ee37a897cc51996431a4dfb10436cblume const int significantBits = (sizeof(uint32_t) * 8) - leadingZeros; 350e2412d5738e4ee37a897cc51996431a4dfb10436cblume // This is making the assumption that the size of a byte is 8 bits 351e2412d5738e4ee37a897cc51996431a4dfb10436cblume // and that sizeof(uint32_t)'s implementation-defined behavior is 4. 352e2412d5738e4ee37a897cc51996431a4dfb10436cblume int mipLevelCount = significantBits; 353e2412d5738e4ee37a897cc51996431a4dfb10436cblume 354e2412d5738e4ee37a897cc51996431a4dfb10436cblume // SkMipMap does not include the base mip level. 355e2412d5738e4ee37a897cc51996431a4dfb10436cblume // For example, it contains levels 1-x instead of 0-x. 356e2412d5738e4ee37a897cc51996431a4dfb10436cblume // This is because the image used to create SkMipMap is the base level. 357e2412d5738e4ee37a897cc51996431a4dfb10436cblume // So subtract 1 from the mip level count. 358e2412d5738e4ee37a897cc51996431a4dfb10436cblume if (mipLevelCount > 0) { 359e2412d5738e4ee37a897cc51996431a4dfb10436cblume --mipLevelCount; 360e2412d5738e4ee37a897cc51996431a4dfb10436cblume } 361e2412d5738e4ee37a897cc51996431a4dfb10436cblume 362e2412d5738e4ee37a897cc51996431a4dfb10436cblume return mipLevelCount; 363e2412d5738e4ee37a897cc51996431a4dfb10436cblume} 364e2412d5738e4ee37a897cc51996431a4dfb10436cblume 365d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com/////////////////////////////////////////////////////////////////////////////// 366d94697c21ae479df4190a1afbf08d85ce244a4efreed@google.com 36733ed3ad9f62b3c84d439b92ab45732d4fa6d05adfmalitabool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const { 36896fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == fLevels) { 3699d93c2ebb31bf996905532446644f242339a774ereed return false; 3709d93c2ebb31bf996905532446644f242339a774ereed } 3719d93c2ebb31bf996905532446644f242339a774ereed 37233ed3ad9f62b3c84d439b92ab45732d4fa6d05adfmalita SkASSERT(scaleSize.width() >= 0 && scaleSize.height() >= 0); 373d10f5b3ac90322071b40e62fb585644ddd767223fmalita 374d10f5b3ac90322071b40e62fb585644ddd767223fmalita#ifndef SK_SUPPORT_LEGACY_ANISOTROPIC_MIPMAP_SCALE 37533ed3ad9f62b3c84d439b92ab45732d4fa6d05adfmalita // Use the smallest scale to match the GPU impl. 37633ed3ad9f62b3c84d439b92ab45732d4fa6d05adfmalita const SkScalar scale = SkTMin(scaleSize.width(), scaleSize.height()); 377d10f5b3ac90322071b40e62fb585644ddd767223fmalita#else 378d10f5b3ac90322071b40e62fb585644ddd767223fmalita // Ideally we'd pick the smaller scale, to match Ganesh. But ignoring one of the 379d10f5b3ac90322071b40e62fb585644ddd767223fmalita // scales can produce some atrocious results, so for now we use the geometric mean. 380d10f5b3ac90322071b40e62fb585644ddd767223fmalita // (https://bugs.chromium.org/p/skia/issues/detail?id=4863) 381d10f5b3ac90322071b40e62fb585644ddd767223fmalita const SkScalar scale = SkScalarSqrt(scaleSize.width() * scaleSize.height()); 382d10f5b3ac90322071b40e62fb585644ddd767223fmalita#endif 38333ed3ad9f62b3c84d439b92ab45732d4fa6d05adfmalita 3847729e56a29a44bd47c69c8dc3247421595940accreed if (scale >= SK_Scalar1 || scale <= 0 || !SkScalarIsFinite(scale)) { 385eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com return false; 386eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com } 387eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com 3887729e56a29a44bd47c69c8dc3247421595940accreed SkScalar L = -SkScalarLog2(scale); 3897729e56a29a44bd47c69c8dc3247421595940accreed if (!SkScalarIsFinite(L)) { 3907729e56a29a44bd47c69c8dc3247421595940accreed return false; 3917729e56a29a44bd47c69c8dc3247421595940accreed } 3927729e56a29a44bd47c69c8dc3247421595940accreed SkASSERT(L >= 0); 393c1e1faae076a26e0706146e490a60d2894835cd5reed// int rndLevel = SkScalarRoundToInt(L); 394c1e1faae076a26e0706146e490a60d2894835cd5reed int level = SkScalarFloorToInt(L); 395c1e1faae076a26e0706146e490a60d2894835cd5reed// SkDebugf("mipmap scale=%g L=%g level=%d rndLevel=%d\n", scale, L, level, rndLevel); 3967729e56a29a44bd47c69c8dc3247421595940accreed 397eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com SkASSERT(level >= 0); 398eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com if (level <= 0) { 399eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com return false; 400eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com } 401eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com 402eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com if (level > fCount) { 403eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com level = fCount; 404eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com } 405eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com if (levelPtr) { 406eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com *levelPtr = fLevels[level - 1]; 407eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com } 408eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com return true; 409eed6f1b76b6690796e3d40993b1504ba1eca2df5reed@google.com} 41067b09bf6b7422c7a3209781cbb7827224e3ffc17reed 4116121405df5689875c7309c20632a82897fce4127cblume// Helper which extracts a pixmap from the src bitmap 41267b09bf6b7422c7a3209781cbb7827224e3ffc17reed// 41367b09bf6b7422c7a3209781cbb7827224e3ffc17reedSkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { 41467b09bf6b7422c7a3209781cbb7827224e3ffc17reed SkAutoPixmapUnlock srcUnlocker; 41567b09bf6b7422c7a3209781cbb7827224e3ffc17reed if (!src.requestLock(&srcUnlocker)) { 41667b09bf6b7422c7a3209781cbb7827224e3ffc17reed return nullptr; 41767b09bf6b7422c7a3209781cbb7827224e3ffc17reed } 41867b09bf6b7422c7a3209781cbb7827224e3ffc17reed const SkPixmap& srcPixmap = srcUnlocker.pixmap(); 41967b09bf6b7422c7a3209781cbb7827224e3ffc17reed // Try to catch where we might have returned nullptr for src crbug.com/492818 42067b09bf6b7422c7a3209781cbb7827224e3ffc17reed if (nullptr == srcPixmap.addr()) { 42167b09bf6b7422c7a3209781cbb7827224e3ffc17reed sk_throw(); 42267b09bf6b7422c7a3209781cbb7827224e3ffc17reed } 42367b09bf6b7422c7a3209781cbb7827224e3ffc17reed return Build(srcPixmap, fact); 42467b09bf6b7422c7a3209781cbb7827224e3ffc17reed} 42567b09bf6b7422c7a3209781cbb7827224e3ffc17reed 426e2412d5738e4ee37a897cc51996431a4dfb10436cblumeint SkMipMap::countLevels() const { 427e2412d5738e4ee37a897cc51996431a4dfb10436cblume return fCount; 428e2412d5738e4ee37a897cc51996431a4dfb10436cblume} 429e2412d5738e4ee37a897cc51996431a4dfb10436cblume 430e2412d5738e4ee37a897cc51996431a4dfb10436cblumebool SkMipMap::getLevel(int index, Level* levelPtr) const { 431e2412d5738e4ee37a897cc51996431a4dfb10436cblume if (NULL == fLevels) { 432e2412d5738e4ee37a897cc51996431a4dfb10436cblume return false; 433e2412d5738e4ee37a897cc51996431a4dfb10436cblume } 434e2412d5738e4ee37a897cc51996431a4dfb10436cblume if (index < 0) { 435e2412d5738e4ee37a897cc51996431a4dfb10436cblume return false; 436e2412d5738e4ee37a897cc51996431a4dfb10436cblume } 437e2412d5738e4ee37a897cc51996431a4dfb10436cblume if (index > fCount - 1) { 438e2412d5738e4ee37a897cc51996431a4dfb10436cblume return false; 439e2412d5738e4ee37a897cc51996431a4dfb10436cblume } 440e2412d5738e4ee37a897cc51996431a4dfb10436cblume if (levelPtr) { 441e2412d5738e4ee37a897cc51996431a4dfb10436cblume *levelPtr = fLevels[index]; 442e2412d5738e4ee37a897cc51996431a4dfb10436cblume } 443e2412d5738e4ee37a897cc51996431a4dfb10436cblume return true; 444e2412d5738e4ee37a897cc51996431a4dfb10436cblume} 445