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 "SkCachedData.h"
12#include "SkPixmap.h"
13#include "SkScalar.h"
14#include "SkSize.h"
15#include "SkShaderBase.h"
16
17class SkBitmap;
18class SkDiscardableMemory;
19
20typedef SkDiscardableMemory* (*SkDiscardableFactoryProc)(size_t bytes);
21
22/*
23 * SkMipMap will generate mipmap levels when given a base mipmap level image.
24 *
25 * Any function which deals with mipmap levels indices will start with index 0
26 * being the first mipmap level which was generated. Said another way, it does
27 * not include the base level in its range.
28 */
29class SkMipMap : public SkCachedData {
30public:
31    static SkMipMap* Build(const SkPixmap& src, SkDestinationSurfaceColorMode,
32                           SkDiscardableFactoryProc);
33    static SkMipMap* Build(const SkBitmap& src, SkDestinationSurfaceColorMode,
34                           SkDiscardableFactoryProc);
35
36    static SkDestinationSurfaceColorMode DeduceColorMode(const SkShaderBase::ContextRec& rec) {
37        return (SkShaderBase::ContextRec::kPMColor_DstType == rec.fPreferredDstType)
38            ? SkDestinationSurfaceColorMode::kLegacy
39            : SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware;
40    }
41
42    // Determines how many levels a SkMipMap will have without creating that mipmap.
43    // This does not include the base mipmap level that the user provided when
44    // creating the SkMipMap.
45    static int ComputeLevelCount(int baseWidth, int baseHeight);
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    struct Level {
53        SkPixmap    fPixmap;
54        SkSize      fScale; // < 1.0
55    };
56
57    bool extractLevel(const SkSize& scale, Level*) const;
58
59    // countLevels returns the number of mipmap levels generated (which does not
60    // include the base mipmap level).
61    int countLevels() const;
62
63    // |index| is an index into the generated mipmap levels. It does not include
64    // the base level. So index 0 represents mipmap level 1.
65    bool getLevel(int index, Level*) const;
66
67protected:
68    void onDataChange(void* oldData, void* newData) override {
69        fLevels = (Level*)newData; // could be nullptr
70    }
71
72private:
73    sk_sp<SkColorSpace> fCS;
74    Level*              fLevels;    // managed by the baseclass, may be null due to onDataChanged.
75    int                 fCount;
76
77    SkMipMap(void* malloc, size_t size) : INHERITED(malloc, size) {}
78    SkMipMap(size_t size, SkDiscardableMemory* dm) : INHERITED(size, dm) {}
79
80    static size_t AllocLevelsSize(int levelCount, size_t pixelSize);
81
82    typedef SkCachedData INHERITED;
83};
84
85#endif
86