1 | /* |
2 | * Copyright 2013 Google Inc. |
3 | * |
4 | * Use of this source code is governed by a BSD-style license that can be |
5 | * found in the LICENSE file. |
6 | */ |
7 | |
8 | #ifndef SkMipmap_DEFINED |
9 | #define SkMipmap_DEFINED |
10 | |
11 | #include "include/core/SkPixmap.h" |
12 | #include "include/core/SkScalar.h" |
13 | #include "include/core/SkSize.h" |
14 | #include "include/private/SkImageInfoPriv.h" |
15 | #include "src/core/SkCachedData.h" |
16 | #include "src/shaders/SkShaderBase.h" |
17 | |
18 | class SkBitmap; |
19 | class SkData; |
20 | class SkDiscardableMemory; |
21 | class SkMipmapBuilder; |
22 | |
23 | typedef SkDiscardableMemory* (*SkDiscardableFactoryProc)(size_t bytes); |
24 | |
25 | /* |
26 | * SkMipmap will generate mipmap levels when given a base mipmap level image. |
27 | * |
28 | * Any function which deals with mipmap levels indices will start with index 0 |
29 | * being the first mipmap level which was generated. Said another way, it does |
30 | * not include the base level in its range. |
31 | */ |
32 | class SkMipmap : public SkCachedData { |
33 | public: |
34 | // Allocate and fill-in a mipmap. If computeContents is false, we just allocated |
35 | // and compute the sizes/rowbytes, but leave the pixel-data uninitialized. |
36 | static SkMipmap* Build(const SkPixmap& src, SkDiscardableFactoryProc, |
37 | bool computeContents = true); |
38 | |
39 | static SkMipmap* Build(const SkBitmap& src, SkDiscardableFactoryProc); |
40 | |
41 | // Determines how many levels a SkMipmap will have without creating that mipmap. |
42 | // This does not include the base mipmap level that the user provided when |
43 | // creating the SkMipmap. |
44 | static int ComputeLevelCount(int baseWidth, int baseHeight); |
45 | static int ComputeLevelCount(SkISize s) { return ComputeLevelCount(s.width(), s.height()); } |
46 | |
47 | // Determines the size of a given mipmap level. |
48 | // |level| is an index into the generated mipmap levels. It does not include |
49 | // the base level. So index 0 represents mipmap level 1. |
50 | static SkISize ComputeLevelSize(int baseWidth, int baseHeight, int level); |
51 | |
52 | // Computes the fractional level based on the scaling in X and Y. |
53 | static float ComputeLevel(SkSize scaleSize); |
54 | |
55 | // We use a block of (possibly discardable) memory to hold an array of Level structs, followed |
56 | // by the pixel data for each level. On 32-bit platforms, Level would naturally be 4 byte |
57 | // aligned, so the pixel data could end up with 4 byte alignment. If the pixel data is F16, |
58 | // it must be 8 byte aligned. To ensure this, keep the Level struct 8 byte aligned as well. |
59 | struct alignas(8) Level { |
60 | SkPixmap fPixmap; |
61 | SkSize fScale; // < 1.0 |
62 | }; |
63 | |
64 | bool (SkSize scale, Level*) const; |
65 | |
66 | // countLevels returns the number of mipmap levels generated (which does not |
67 | // include the base mipmap level). |
68 | int countLevels() const; |
69 | |
70 | // |index| is an index into the generated mipmap levels. It does not include |
71 | // the base level. So index 0 represents mipmap level 1. |
72 | bool getLevel(int index, Level*) const; |
73 | |
74 | bool validForRootLevel(const SkImageInfo&) const; |
75 | |
76 | sk_sp<SkData> serialize() const; |
77 | static bool Deserialize(SkMipmapBuilder*, const void* data, size_t size); |
78 | |
79 | protected: |
80 | void onDataChange(void* oldData, void* newData) override { |
81 | fLevels = (Level*)newData; // could be nullptr |
82 | } |
83 | |
84 | private: |
85 | sk_sp<SkColorSpace> fCS; |
86 | Level* fLevels; // managed by the baseclass, may be null due to onDataChanged. |
87 | int fCount; |
88 | |
89 | SkMipmap(void* malloc, size_t size) : INHERITED(malloc, size) {} |
90 | SkMipmap(size_t size, SkDiscardableMemory* dm) : INHERITED(size, dm) {} |
91 | |
92 | static size_t AllocLevelsSize(int levelCount, size_t pixelSize); |
93 | |
94 | typedef SkCachedData INHERITED; |
95 | }; |
96 | |
97 | #endif |
98 | |