1/*
2 * Copyright 2016 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 SkSpecialImage_DEFINED
9#define SkSpecialImage_DEFINED
10
11#include "SkNextID.h"
12#include "SkRefCnt.h"
13#include "SkSurfaceProps.h"
14
15#include "SkImageFilter.h" // for OutputProperties
16#include "SkImageInfo.h"   // for SkAlphaType
17
18class GrContext;
19class GrSurfaceProxy;
20class GrTexture;
21class GrTextureProxy;
22class SkBitmap;
23class SkCanvas;
24class SkImage;
25struct SkImageInfo;
26class SkPaint;
27class SkPixmap;
28class SkSpecialSurface;
29class SkSurface;
30
31enum {
32    kNeedNewImageUniqueID_SpecialImage = 0
33};
34
35/**
36 * This is a restricted form of SkImage solely intended for internal use. It
37 * differs from SkImage in that:
38 *      - it can only be backed by raster or gpu (no generators)
39 *      - it can be backed by a GrTextureProxy larger than its nominal bounds
40 *      - it can't be drawn tiled
41 *      - it can't be drawn with MIPMAPs
42 * It is similar to SkImage in that it abstracts how the pixels are stored/represented.
43 *
44 * Note: the contents of the backing storage outside of the subset rect are undefined.
45 */
46class SkSpecialImage : public SkRefCnt {
47public:
48    typedef void* ReleaseContext;
49    typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext);
50
51    const SkSurfaceProps& props() const { return fProps; }
52
53    int width() const { return fSubset.width(); }
54    int height() const { return fSubset.height(); }
55    const SkIRect& subset() const { return fSubset; }
56    SkColorSpace* getColorSpace() const;
57
58    uint32_t uniqueID() const { return fUniqueID; }
59    virtual SkAlphaType alphaType() const = 0;
60    virtual size_t getSize() const = 0;
61
62    /**
63     *  Ensures that a special image is backed by a texture (when GrContext is non-null). If no
64     *  transformation is required, the returned image may be the same as this special image.
65     *  If this special image is from a different GrContext, this will fail.
66     */
67    sk_sp<SkSpecialImage> makeTextureImage(GrContext*);
68
69    /**
70     *  Draw this SpecialImage into the canvas.
71     */
72    void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const;
73
74    static sk_sp<SkSpecialImage> MakeFromImage(const SkIRect& subset,
75                                               sk_sp<SkImage>,
76                                               SkColorSpace* dstColorSpace,
77                                               const SkSurfaceProps* = nullptr);
78    static sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset,
79                                                const SkBitmap&,
80                                                const SkSurfaceProps* = nullptr);
81#if SK_SUPPORT_GPU
82    static sk_sp<SkSpecialImage> MakeDeferredFromGpu(GrContext*,
83                                                     const SkIRect& subset,
84                                                     uint32_t uniqueID,
85                                                     sk_sp<GrTextureProxy>,
86                                                     sk_sp<SkColorSpace>,
87                                                     const SkSurfaceProps* = nullptr,
88                                                     SkAlphaType at = kPremul_SkAlphaType);
89#endif
90
91    /**
92     *  Create a new special surface with a backend that is compatible with this special image.
93     */
94    sk_sp<SkSpecialSurface> makeSurface(const SkImageFilter::OutputProperties& outProps,
95                                        const SkISize& size,
96                                        SkAlphaType at = kPremul_SkAlphaType) const;
97
98    /**
99     * Create a new surface with a backend that is compatible with this special image.
100     * TODO: switch this to makeSurface once we resolved the naming issue
101     */
102    sk_sp<SkSurface> makeTightSurface(const SkImageFilter::OutputProperties& outProps,
103                                      const SkISize& size,
104                                      SkAlphaType at = kPremul_SkAlphaType) const;
105
106    /**
107     * Extract a subset of this special image and return it as a special image.
108     * It may or may not point to the same backing memory.
109     */
110    sk_sp<SkSpecialImage> makeSubset(const SkIRect& subset) const;
111
112    /**
113     * Create an SkImage from the contents of this special image optionally extracting a subset.
114     * It may or may not point to the same backing memory.
115     * Note: when no 'subset' parameter is specified the the entire SkSpecialImage will be
116     * returned - including whatever extra padding may have resulted from a loose fit!
117     * When the 'subset' parameter is specified the returned image will be tight even if that
118     * entails a copy!
119     */
120    sk_sp<SkImage> asImage(const SkIRect* subset = nullptr) const;
121
122    // TODO: hide this when GrLayerHoister uses SkSpecialImages more fully (see skbug.com/5063)
123    /**
124     *  If the SpecialImage is backed by a gpu texture, return true.
125     */
126    bool isTextureBacked() const;
127
128    /**
129     * Return the GrContext if the SkSpecialImage is GrTexture-backed
130     */
131    GrContext* getContext() const;
132
133#if SK_SUPPORT_GPU
134    /**
135     *  Regardless of the underlying backing store, return the contents as a GrTextureProxy.
136     *  The active portion of the texture can be retrieved via 'subset'.
137     */
138    sk_sp<GrTextureProxy> asTextureProxyRef(GrContext*) const;
139#endif
140
141    // TODO: hide this whe the imagefilter all have a consistent draw path (see skbug.com/5063)
142    /**
143     *  Regardless of the underlying backing store, return the contents as an SkBitmap
144     *
145     *  The returned ImageInfo represents the backing memory. Use 'subset'
146     *  to get the active portion's dimensions.
147     */
148    bool getROPixels(SkBitmap*) const;
149
150protected:
151    SkSpecialImage(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps*);
152
153private:
154    const SkSurfaceProps fProps;
155    const SkIRect        fSubset;
156    const uint32_t       fUniqueID;
157
158    typedef SkRefCnt INHERITED;
159};
160
161#endif
162