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