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 SkDiscardableMemory;
20 
21 typedef SkDiscardableMemory* (*SkDiscardableFactoryProc)(size_t bytes);
22 
23 /*
24  * SkMipMap will generate mipmap levels when given a base mipmap level image.
25  *
26  * Any function which deals with mipmap levels indices will start with index 0
27  * being the first mipmap level which was generated. Said another way, it does
28  * not include the base level in its range.
29  */
30 class SkMipMap : public SkCachedData {
31 public:
32     static SkMipMap* Build(const SkPixmap& src, SkDiscardableFactoryProc);
33     static SkMipMap* Build(const SkBitmap& src, SkDiscardableFactoryProc);
34 
35     // Determines how many levels a SkMipMap will have without creating that mipmap.
36     // This does not include the base mipmap level that the user provided when
37     // creating the SkMipMap.
38     static int ComputeLevelCount(int baseWidth, int baseHeight);
39 
40     // Determines the size of a given mipmap level.
41     // |level| is an index into the generated mipmap levels. It does not include
42     // the base level. So index 0 represents mipmap level 1.
43     static SkISize ComputeLevelSize(int baseWidth, int baseHeight, int level);
44 
45     // We use a block of (possibly discardable) memory to hold an array of Level structs, followed
46     // by the pixel data for each level. On 32-bit platforms, Level would naturally be 4 byte
47     // aligned, so the pixel data could end up with 4 byte alignment. If the pixel data is F16,
48     // it must be 8 byte aligned. To ensure this, keep the Level struct 8 byte aligned as well.
49     struct alignas(8) Level {
50         SkPixmap    fPixmap;
51         SkSize      fScale; // < 1.0
52     };
53 
54     bool extractLevel(const SkSize& scale, Level*) const;
55 
56     // countLevels returns the number of mipmap levels generated (which does not
57     // include the base mipmap level).
58     int countLevels() const;
59 
60     // |index| is an index into the generated mipmap levels. It does not include
61     // the base level. So index 0 represents mipmap level 1.
62     bool getLevel(int index, Level*) const;
63 
64 protected:
onDataChange(void * oldData,void * newData)65     void onDataChange(void* oldData, void* newData) override {
66         fLevels = (Level*)newData; // could be nullptr
67     }
68 
69 private:
70     sk_sp<SkColorSpace> fCS;
71     Level*              fLevels;    // managed by the baseclass, may be null due to onDataChanged.
72     int                 fCount;
73 
SkMipMap(void * malloc,size_t size)74     SkMipMap(void* malloc, size_t size) : INHERITED(malloc, size) {}
SkMipMap(size_t size,SkDiscardableMemory * dm)75     SkMipMap(size_t size, SkDiscardableMemory* dm) : INHERITED(size, dm) {}
76 
77     static size_t AllocLevelsSize(int levelCount, size_t pixelSize);
78 
79     typedef SkCachedData INHERITED;
80 };
81 
82 #endif
83