1/*
2 * Copyright 2017 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 SkGr_DEFINED
9#define SkGr_DEFINED
10
11#include "include/core/SkCanvas.h"
12#include "include/core/SkColor.h"
13#include "include/core/SkFilterQuality.h"
14#include "include/core/SkImageInfo.h"
15#include "include/gpu/GrTypes.h"
16#include "include/private/SkColorData.h"
17#include "src/core/SkBlendModePriv.h"
18#include "src/gpu/GrBlend.h"
19#include "src/gpu/GrCaps.h"
20#include "src/gpu/GrColor.h"
21#include "src/gpu/GrSamplerState.h"
22
23class GrCaps;
24class GrColorInfo;
25class GrColorSpaceXform;
26class GrDirectContext;
27class GrFragmentProcessor;
28class GrPaint;
29class GrRecordingContext;
30class GrResourceProvider;
31class GrTextureProxy;
32class GrUniqueKey;
33class SkBitmap;
34class SkData;
35class SkMatrix;
36class SkMatrixProvider;
37class SkPaint;
38class SkPixelRef;
39class SkPixmap;
40struct SkIRect;
41
42////////////////////////////////////////////////////////////////////////////////
43// Color type conversions
44
45static inline GrColor SkColorToPremulGrColor(SkColor c) {
46 SkPMColor pm = SkPreMultiplyColor(c);
47 unsigned r = SkGetPackedR32(pm);
48 unsigned g = SkGetPackedG32(pm);
49 unsigned b = SkGetPackedB32(pm);
50 unsigned a = SkGetPackedA32(pm);
51 return GrColorPackRGBA(r, g, b, a);
52}
53
54static inline GrColor SkColorToUnpremulGrColor(SkColor c) {
55 unsigned r = SkColorGetR(c);
56 unsigned g = SkColorGetG(c);
57 unsigned b = SkColorGetB(c);
58 unsigned a = SkColorGetA(c);
59 return GrColorPackRGBA(r, g, b, a);
60}
61
62/** Similar, but using SkPMColor4f. */
63SkPMColor4f SkColorToPMColor4f(SkColor, const GrColorInfo&);
64
65/** Converts an SkColor4f to the destination color space. */
66SkColor4f SkColor4fPrepForDst(SkColor4f, const GrColorInfo&);
67
68////////////////////////////////////////////////////////////////////////////////
69// SkTileMode conversion
70
71static constexpr GrSamplerState::WrapMode SkTileModeToWrapMode(SkTileMode tileMode) {
72 switch (tileMode) {
73 case SkTileMode::kClamp: return GrSamplerState::WrapMode::kClamp;
74 case SkTileMode::kDecal: return GrSamplerState::WrapMode::kClampToBorder;
75 case SkTileMode::kMirror: return GrSamplerState::WrapMode::kMirrorRepeat;
76 case SkTileMode::kRepeat: return GrSamplerState::WrapMode::kRepeat;
77 }
78 SkUNREACHABLE;
79}
80
81////////////////////////////////////////////////////////////////////////////////
82// Paint conversion
83
84/** Converts an SkPaint to a GrPaint for a given GrRecordingContext. The matrix is required in order
85 to convert the SkShader (if any) on the SkPaint. The primitive itself has no color. */
86bool SkPaintToGrPaint(GrRecordingContext*,
87 const GrColorInfo& dstColorInfo,
88 const SkPaint& skPaint,
89 const SkMatrixProvider& matrixProvider,
90 GrPaint* grPaint);
91
92/** Same as above but ignores the SkShader (if any) on skPaint. */
93bool SkPaintToGrPaintNoShader(GrRecordingContext*,
94 const GrColorInfo& dstColorInfo,
95 const SkPaint& skPaint,
96 const SkMatrixProvider& matrixProvider,
97 GrPaint* grPaint);
98
99/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. The processor
100 should expect an unpremul input color and produce a premultiplied output color. There is
101 no primitive color. */
102bool SkPaintToGrPaintReplaceShader(GrRecordingContext*,
103 const GrColorInfo& dstColorInfo,
104 const SkPaint& skPaint,
105 const SkMatrixProvider& matrixProvider,
106 std::unique_ptr<GrFragmentProcessor> shaderFP,
107 GrPaint* grPaint);
108
109/** Blends the SkPaint's shader (or color if no shader) with the color which specified via a
110 GrOp's GrPrimitiveProcesssor. */
111bool SkPaintToGrPaintWithBlend(GrRecordingContext*,
112 const GrColorInfo& dstColorInfo,
113 const SkPaint& skPaint,
114 const SkMatrixProvider& matrixProvider,
115 SkBlendMode primColorMode,
116 GrPaint* grPaint);
117
118/** This is used when there is a primitive color, but the shader should be ignored. Currently,
119 the expectation is that the primitive color will be premultiplied, though it really should be
120 unpremultiplied so that interpolation is done in unpremul space. The paint's alpha will be
121 applied to the primitive color after interpolation. */
122inline bool SkPaintToGrPaintWithPrimitiveColor(GrRecordingContext* context,
123 const GrColorInfo& dstColorInfo,
124 const SkPaint& skPaint,
125 const SkMatrixProvider& matrixProvider,
126 GrPaint* grPaint) {
127 return SkPaintToGrPaintWithBlend(context, dstColorInfo, skPaint, matrixProvider,
128 SkBlendMode::kDst, grPaint);
129}
130
131/** This is used when there may or may not be a shader, and the caller wants to plugin a texture
132 lookup. If there is a shader, then its output will only be used if the texture is alpha8. */
133bool SkPaintToGrPaintWithTexture(GrRecordingContext*,
134 const GrColorInfo& dstColorInfo,
135 const SkPaint& skPaint,
136 const SkMatrixProvider& matrixProvider,
137 std::unique_ptr<GrFragmentProcessor> fp,
138 bool textureIsAlphaOnly,
139 GrPaint* grPaint);
140
141////////////////////////////////////////////////////////////////////////////////
142// Misc Sk to Gr type conversions
143
144/**
145 * Determines how to interpret SkFilterQuality given draw params and canvas state. If the returned
146 * bool is true then bicubic filtering should be used (and the two other return values can be
147 * ignored).
148 */
149std::tuple<GrSamplerState::Filter,
150 GrSamplerState::MipmapMode,
151 bool /*bicubic*/>
152GrInterpretFilterQuality(SkISize imageDims,
153 SkFilterQuality paintFilterQuality,
154 const SkMatrix& viewM,
155 const SkMatrix& localM,
156 bool sharpenMipmappedTextures);
157
158//////////////////////////////////////////////////////////////////////////////
159
160static_assert((int)kZero_GrBlendCoeff == (int)SkBlendModeCoeff::kZero);
161static_assert((int)kOne_GrBlendCoeff == (int)SkBlendModeCoeff::kOne);
162static_assert((int)kSC_GrBlendCoeff == (int)SkBlendModeCoeff::kSC);
163static_assert((int)kISC_GrBlendCoeff == (int)SkBlendModeCoeff::kISC);
164static_assert((int)kDC_GrBlendCoeff == (int)SkBlendModeCoeff::kDC);
165static_assert((int)kIDC_GrBlendCoeff == (int)SkBlendModeCoeff::kIDC);
166static_assert((int)kSA_GrBlendCoeff == (int)SkBlendModeCoeff::kSA);
167static_assert((int)kISA_GrBlendCoeff == (int)SkBlendModeCoeff::kISA);
168static_assert((int)kDA_GrBlendCoeff == (int)SkBlendModeCoeff::kDA);
169static_assert((int)kIDA_GrBlendCoeff == (int)SkBlendModeCoeff::kIDA);
170// static_assert(SkXfermode::kCoeffCount == 10);
171
172////////////////////////////////////////////////////////////////////////////////
173// Texture management
174
175/**
176 * Policies for how to create textures for SkImages (and SkBitmaps).
177 */
178enum class GrImageTexGenPolicy : int {
179 // Choose the cheapest way to generate the texture. Use GrResourceCache if appropriate.
180 kDraw,
181 // Always make a new texture that is uncached and unbudgeted.
182 kNew_Uncached_Unbudgeted,
183 // Always make a new texture that is uncached and budgeted.
184 kNew_Uncached_Budgeted
185};
186
187/**
188 * Returns a view that wraps a texture representing the bitmap. The texture is inserted into the
189 * cache (unless the bitmap is marked volatile and can be retrieved again via this function.
190 * A MIP mapped texture may be returned even when GrMipmapped is kNo. The function will succeed
191 * with a non-MIP mapped texture if GrMipmapped is kYes but MIP mapping is not supported.
192 */
193GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext*, const SkBitmap&, GrMipmapped);
194
195/**
196 * Creates a new texture with mipmap levels and copies the baseProxy into the base layer.
197 */
198sk_sp<GrSurfaceProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext*,
199 GrSurfaceProxy* baseProxy,
200 GrSurfaceOrigin origin,
201 SkBudgeted = SkBudgeted::kYes);
202/**
203 * Same as GrCopyBaseMipMapToTextureProxy but takes the src as a view and returns a view with same
204 * origin and swizzle as the src view.
205 */
206GrSurfaceProxyView GrCopyBaseMipMapToView(GrRecordingContext*,
207 GrSurfaceProxyView,
208 SkBudgeted = SkBudgeted::kYes);
209
210/*
211 * Create a texture proxy from the provided bitmap and add it to the texture cache
212 * using the key also extracted from 'bitmp'.
213 */
214GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext*, const SkBitmap& bitmap);
215
216/**
217 * Our key includes the offset, width, and height so that bitmaps created by extractSubset()
218 * are unique.
219 *
220 * The imageID is in the shared namespace (see SkNextID::ImageID())
221 * - SkBitmap/SkPixelRef
222 * - SkImage
223 * - SkImageGenerator
224 */
225void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds);
226
227/**
228 * Makes a SkIDChangeListener from a GrUniqueKey. The key will be invalidated in the resource
229 * cache if the ID becomes invalid. This also modifies the key so that it will cause the listener
230 * to be deregistered if the key is destroyed (to prevent unbounded listener growth when resources
231 * are purged before listeners trigger).
232 */
233sk_sp<SkIDChangeListener> GrMakeUniqueKeyInvalidationListener(GrUniqueKey*, uint32_t contextID);
234
235#endif
236