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
18class SkBitmap;
19class SkData;
20class SkDiscardableMemory;
21class SkMipmapBuilder;
22
23typedef 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 */
32class SkMipmap : public SkCachedData {
33public:
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 extractLevel(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
79protected:
80 void onDataChange(void* oldData, void* newData) override {
81 fLevels = (Level*)newData; // could be nullptr
82 }
83
84private:
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