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 * Draw this SpecialImage into the canvas, automatically taking into account the image's subset
66 */
67 void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const;
68
69 static sk_sp<SkSpecialImage> MakeFromImage(GrRecordingContext*,
70 const SkIRect& subset,
71 sk_sp<SkImage>,
72 const SkSurfaceProps* = nullptr);
73 static sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset,
74 const SkBitmap&,
75 const SkSurfaceProps* = nullptr);
76 static sk_sp<SkSpecialImage> CopyFromRaster(const SkIRect& subset,
77 const SkBitmap&,
78 const SkSurfaceProps* = nullptr);
79#if SK_SUPPORT_GPU
80 static sk_sp<SkSpecialImage> MakeDeferredFromGpu(GrRecordingContext*,
81 const SkIRect& subset,
82 uint32_t uniqueID,
83 GrSurfaceProxyView,
84 GrColorType,
85 sk_sp<SkColorSpace>,
86 const SkSurfaceProps* = nullptr,
87 SkAlphaType at = kPremul_SkAlphaType);
88#endif
89
90 /**
91 * Create a new special surface with a backend that is compatible with this special image.
92 */
93 sk_sp<SkSpecialSurface> makeSurface(SkColorType colorType,
94 const SkColorSpace* colorSpace,
95 const SkISize& size,
96 SkAlphaType at = kPremul_SkAlphaType,
97 const SkSurfaceProps* props = nullptr) const;
98
99 /**
100 * Create a new surface with a backend that is compatible with this special image.
101 * TODO: switch this to makeSurface once we resolved the naming issue
102 * TODO (michaelludwig) - This is only used by SkTileImageFilter, which appears should be
103 * updated to work correctly with subsets and then makeTightSurface() can go away entirely.
104 */
105 sk_sp<SkSurface> makeTightSurface(SkColorType colorType,
106 const SkColorSpace* colorSpace,
107 const SkISize& size,
108 SkAlphaType at = kPremul_SkAlphaType) const;
109
110 /**
111 * Extract a subset of this special image and return it as a special image.
112 * It may or may not point to the same backing memory. The input 'subset' is relative to the
113 * special image's content rect.
114 */
115 sk_sp<SkSpecialImage> makeSubset(const SkIRect& subset) const;
116
117 /**
118 * Create an SkImage from the contents of this special image optionally extracting a subset.
119 * It may or may not point to the same backing memory.
120 * Note: when no 'subset' parameter is specified the the entire SkSpecialImage will be
121 * returned - including whatever extra padding may have resulted from a loose fit!
122 * When the 'subset' parameter is specified the returned image will be tight even if that
123 * entails a copy! The 'subset' is relative to this special image's content rect.
124 */
125 sk_sp<SkImage> asImage(const SkIRect* subset = nullptr) const;
126
127 /**
128 * If the SpecialImage is backed by a gpu texture, return true.
129 */
130 bool isTextureBacked() const;
131
132 /**
133 * Return the GrRecordingContext if the SkSpecialImage is GrTexture-backed
134 */
135 GrRecordingContext* getContext() const;
136
137#if SK_SUPPORT_GPU
138 /**
139 * Regardless of how the underlying backing data is stored, returns the contents as a
140 * GrSurfaceProxyView. The returned view's proxy represents the entire backing image, so texture
141 * coordinates must be mapped from the content rect (e.g. relative to 'subset()') to the proxy's
142 * space (offset by subset().topLeft()).
143 */
144 GrSurfaceProxyView view(GrRecordingContext*) const;
145#endif
146
147 /**
148 * Regardless of the underlying backing store, return the contents as an SkBitmap.
149 * The returned bitmap represents the subset accessed by this image, thus (0,0) refers to the
150 * top-left corner of 'subset'.
151 */
152 bool getROPixels(SkBitmap*) const;
153
154protected:
155 SkSpecialImage(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps*);
156
157private:
158 const SkSurfaceProps fProps;
159 const SkIRect fSubset;
160 const uint32_t fUniqueID;
161
162 typedef SkRefCnt INHERITED;
163};
164
165#endif
166