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 "include/core/SkImageInfo.h"
12#include "include/core/SkRefCnt.h"
13#include "include/core/SkSurfaceProps.h"
14#include "src/core/SkNextID.h"
15
16#if SK_SUPPORT_GPU
17#include "include/private/GrTypesPriv.h"
18#include "src/gpu/GrSurfaceProxyView.h"
19#endif
20
21class GrRecordingContext;
22class GrTextureProxy;
23class SkBitmap;
24class SkCanvas;
25class SkImage;
26struct SkImageInfo;
27class SkPaint;
28class SkPixmap;
29class SkSpecialSurface;
30class SkSurface;
31
32enum {
33 kNeedNewImageUniqueID_SpecialImage = 0
34};
35
36/**
37 * This is a restricted form of SkImage solely intended for internal use. It
38 * differs from SkImage in that:
39 * - it can only be backed by raster or gpu (no generators)
40 * - it can be backed by a GrTextureProxy larger than its nominal bounds
41 * - it can't be drawn tiled
42 * - it can't be drawn with MIPMAPs
43 * It is similar to SkImage in that it abstracts how the pixels are stored/represented.
44 *
45 * Note: the contents of the backing storage outside of the subset rect are undefined.
46 */
47class SkSpecialImage : public SkRefCnt {
48public:
49 typedef void* ReleaseContext;
50 typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext);
51
52 const SkSurfaceProps& props() const { return fProps; }
53
54 int width() const { return fSubset.width(); }
55 int height() const { return fSubset.height(); }
56 const SkIRect& subset() const { return fSubset; }
57 SkColorSpace* getColorSpace() const;
58
59 uint32_t uniqueID() const { return fUniqueID; }
60 virtual SkAlphaType alphaType() const = 0;
61 virtual SkColorType colorType() const = 0;
62 virtual size_t getSize() const = 0;
63
64 /**
65 * Ensures that a special image is backed by a texture (when GrRecordingContext is non-null).
66 * If no transformation is required, the returned image may be the same as this special image.
67 * If this special image is from a different GrRecordingContext, this will fail.
68 */
69 sk_sp<SkSpecialImage> makeTextureImage(GrRecordingContext*) const;
70
71 /**
72 * Draw this SpecialImage into the canvas, automatically taking into account the image's subset
73 */
74 void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const;
75
76 static sk_sp<SkSpecialImage> MakeFromImage(GrRecordingContext*,
77 const SkIRect& subset,
78 sk_sp<SkImage>,
79 const SkSurfaceProps* = nullptr);
80 static sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset,
81 const SkBitmap&,
82 const SkSurfaceProps* = nullptr);
83 static sk_sp<SkSpecialImage> CopyFromRaster(const SkIRect& subset,
84 const SkBitmap&,
85 const SkSurfaceProps* = nullptr);
86#if SK_SUPPORT_GPU
87 static sk_sp<SkSpecialImage> MakeDeferredFromGpu(GrRecordingContext*,
88 const SkIRect& subset,
89 uint32_t uniqueID,
90 GrSurfaceProxyView,
91 GrColorType,
92 sk_sp<SkColorSpace>,
93 const SkSurfaceProps* = nullptr,
94 SkAlphaType at = kPremul_SkAlphaType);
95#endif
96
97 /**
98 * Create a new special surface with a backend that is compatible with this special image.
99 */
100 sk_sp<SkSpecialSurface> makeSurface(SkColorType colorType,
101 const SkColorSpace* colorSpace,
102 const SkISize& size,
103 SkAlphaType at = kPremul_SkAlphaType,
104 const SkSurfaceProps* props = nullptr) const;
105
106 /**
107 * Create a new surface with a backend that is compatible with this special image.
108 * TODO: switch this to makeSurface once we resolved the naming issue
109 * TODO (michaelludwig) - This is only used by SkTileImageFilter, which appears should be
110 * updated to work correctly with subsets and then makeTightSurface() can go away entirely.
111 */
112 sk_sp<SkSurface> makeTightSurface(SkColorType colorType,
113 const SkColorSpace* colorSpace,
114 const SkISize& size,
115 SkAlphaType at = kPremul_SkAlphaType) const;
116
117 /**
118 * Extract a subset of this special image and return it as a special image.
119 * It may or may not point to the same backing memory. The input 'subset' is relative to the
120 * special image's content rect.
121 */
122 sk_sp<SkSpecialImage> makeSubset(const SkIRect& subset) const;
123
124 /**
125 * Create an SkImage from the contents of this special image optionally extracting a subset.
126 * It may or may not point to the same backing memory.
127 * Note: when no 'subset' parameter is specified the the entire SkSpecialImage will be
128 * returned - including whatever extra padding may have resulted from a loose fit!
129 * When the 'subset' parameter is specified the returned image will be tight even if that
130 * entails a copy! The 'subset' is relative to this special image's content rect.
131 */
132 sk_sp<SkImage> asImage(const SkIRect* subset = nullptr) const;
133
134 /**
135 * If the SpecialImage is backed by a gpu texture, return true.
136 */
137 bool isTextureBacked() const;
138
139 /**
140 * Return the GrRecordingContext if the SkSpecialImage is GrTexture-backed
141 */
142 GrRecordingContext* getContext() const;
143
144#if SK_SUPPORT_GPU
145 /**
146 * Regardless of how the underlying backing data is stored, returns the contents as a
147 * GrSurfaceProxyView. The returned view's proxy represents the entire backing image, so texture
148 * coordinates must be mapped from the content rect (e.g. relative to 'subset()') to the proxy's
149 * space (offset by subset().topLeft()).
150 */
151 GrSurfaceProxyView view(GrRecordingContext*) const;
152#endif
153
154 /**
155 * Regardless of the underlying backing store, return the contents as an SkBitmap.
156 * The returned bitmap represents the subset accessed by this image, thus (0,0) refers to the
157 * top-left corner of 'subset'.
158 */
159 bool getROPixels(SkBitmap*) const;
160
161protected:
162 SkSpecialImage(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps*);
163
164private:
165 const SkSurfaceProps fProps;
166 const SkIRect fSubset;
167 const uint32_t fUniqueID;
168
169 typedef SkRefCnt INHERITED;
170};
171
172#endif
173