1/*
2 * Copyright 2015 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 SkImageCacherator_DEFINED
9#define SkImageCacherator_DEFINED
10
11#include "SkImageGenerator.h"
12#include "SkMutex.h"
13#include "SkTemplates.h"
14
15class GrContext;
16class GrTextureParams;
17class GrUniqueKey;
18class SkBitmap;
19class SkImage;
20
21/*
22 *  Internal class to manage caching the output of an ImageGenerator.
23 */
24class SkImageCacherator {
25public:
26    // Takes ownership of the generator
27    static SkImageCacherator* NewFromGenerator(SkImageGenerator*, const SkIRect* subset = nullptr);
28
29    const SkImageInfo& info() const { return fInfo; }
30    uint32_t uniqueID() const { return fUniqueID; }
31
32    /**
33     *  On success (true), bitmap will point to the pixels for this generator. If this returns
34     *  false, the bitmap will be reset to empty.
35     *
36     *  If not NULL, the client will be notified (->notifyAddedToCache()) when resources are
37     *  added to the cache on its behalf.
38     */
39    bool lockAsBitmap(SkBitmap*, const SkImage* client,
40                      SkImage::CachingHint = SkImage::kAllow_CachingHint);
41
42    /**
43     *  Returns a ref() on the texture produced by this generator. The caller must call unref()
44     *  when it is done. Will return nullptr on failure.
45     *
46     *  If not NULL, the client will be notified (->notifyAddedToCache()) when resources are
47     *  added to the cache on its behalf.
48     *
49     *  The caller is responsible for calling texture->unref() when they are done.
50     */
51    GrTexture* lockAsTexture(GrContext*, const GrTextureParams&, const SkImage* client,
52                             SkImage::CachingHint = SkImage::kAllow_CachingHint);
53
54    /**
55     *  If the underlying src naturally is represented by an encoded blob (in SkData), this returns
56     *  a ref to that data. If not, it returns null.
57     *
58     *  If a GrContext is specified, then the caller is only interested in gpu-specific encoded
59     *  formats, so others (e.g. PNG) can just return nullptr.
60     */
61    SkData* refEncoded(GrContext*);
62
63    // Only return true if the generate has already been cached.
64    bool lockAsBitmapOnlyIfAlreadyCached(SkBitmap*);
65    // Call the underlying generator directly
66    bool directGeneratePixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
67                              int srcX, int srcY);
68
69private:
70    SkImageCacherator(SkImageGenerator*, const SkImageInfo&, const SkIPoint&, uint32_t uniqueID);
71
72    bool generateBitmap(SkBitmap*);
73    bool tryLockAsBitmap(SkBitmap*, const SkImage*, SkImage::CachingHint);
74#if SK_SUPPORT_GPU
75    // Returns the texture. If the cacherator is generating the texture and wants to cache it,
76    // it should use the passed in key (if the key is valid).
77    GrTexture* lockTexture(GrContext*, const GrUniqueKey& key, const SkImage* client,
78                           SkImage::CachingHint);
79#endif
80
81    class ScopedGenerator {
82        SkImageCacherator* fCacher;
83    public:
84        ScopedGenerator(SkImageCacherator* cacher) : fCacher(cacher) {
85            fCacher->fMutexForGenerator.acquire();
86        }
87        ~ScopedGenerator() {
88            fCacher->fMutexForGenerator.release();
89        }
90        SkImageGenerator* operator->() const { return fCacher->fNotThreadSafeGenerator; }
91        operator SkImageGenerator*() const { return fCacher->fNotThreadSafeGenerator; }
92    };
93
94    SkMutex                         fMutexForGenerator;
95    SkAutoTDelete<SkImageGenerator> fNotThreadSafeGenerator;
96
97    const SkImageInfo   fInfo;
98    const SkIPoint      fOrigin;
99    const uint32_t      fUniqueID;
100
101    friend class GrImageTextureMaker;
102};
103
104#endif
105