OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
| 8 #include "GrTextureMaker.h" |
| 9 |
8 #include "SkGr.h" | 10 #include "SkGr.h" |
9 | 11 |
10 #include "GrCaps.h" | 12 #include "GrCaps.h" |
| 13 #include "GrContext.h" |
11 #include "GrDrawContext.h" | 14 #include "GrDrawContext.h" |
12 #include "GrXferProcessor.h" | 15 #include "GrXferProcessor.h" |
13 #include "GrYUVProvider.h" | 16 #include "GrYUVProvider.h" |
14 | 17 |
15 #include "SkColorFilter.h" | 18 #include "SkColorFilter.h" |
16 #include "SkConfig8888.h" | 19 #include "SkConfig8888.h" |
17 #include "SkCanvas.h" | 20 #include "SkCanvas.h" |
18 #include "SkData.h" | 21 #include "SkData.h" |
19 #include "SkErrorInternals.h" | 22 #include "SkErrorInternals.h" |
20 #include "SkGrPixelRef.h" | 23 #include "SkGrPixelRef.h" |
21 #include "SkMessageBus.h" | 24 #include "SkMessageBus.h" |
| 25 #include "SkMath.h" |
| 26 #include "SkMipMap.h" |
| 27 #include "SkMipMapLevel.h" |
22 #include "SkPixelRef.h" | 28 #include "SkPixelRef.h" |
23 #include "SkResourceCache.h" | 29 #include "SkResourceCache.h" |
24 #include "SkTextureCompressor.h" | 30 #include "SkTextureCompressor.h" |
| 31 #include "SkTypes.h" |
25 #include "SkYUVPlanesCache.h" | 32 #include "SkYUVPlanesCache.h" |
26 #include "effects/GrBicubicEffect.h" | 33 #include "effects/GrBicubicEffect.h" |
| 34 #include "effects/GrConstColorProcessor.h" |
27 #include "effects/GrDitherEffect.h" | 35 #include "effects/GrDitherEffect.h" |
28 #include "effects/GrPorterDuffXferProcessor.h" | 36 #include "effects/GrPorterDuffXferProcessor.h" |
| 37 #include "effects/GrXfermodeFragmentProcessor.h" |
29 #include "effects/GrYUVtoRGBEffect.h" | 38 #include "effects/GrYUVtoRGBEffect.h" |
30 | 39 |
31 #ifndef SK_IGNORE_ETC1_SUPPORT | 40 #ifndef SK_IGNORE_ETC1_SUPPORT |
32 # include "ktx.h" | 41 # include "ktx.h" |
33 # include "etc1.h" | 42 # include "etc1.h" |
34 #endif | 43 #endif |
35 | 44 |
36 /* Fill out buffer with the compressed format Ganesh expects from a colortable | 45 /* Fill out buffer with the compressed format Ganesh expects from a colortable |
37 based bitmap. [palette (colortable) + indices]. | 46 based bitmap. [palette (colortable) + indices]. |
38 | 47 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 for (int y = 0; y < bitmap.height(); y++) { | 94 for (int y = 0; y < bitmap.height(); y++) { |
86 memcpy(dst, src, width); | 95 memcpy(dst, src, width); |
87 src += rowBytes; | 96 src += rowBytes; |
88 dst += width; | 97 dst += width; |
89 } | 98 } |
90 } | 99 } |
91 } | 100 } |
92 | 101 |
93 //////////////////////////////////////////////////////////////////////////////// | 102 //////////////////////////////////////////////////////////////////////////////// |
94 | 103 |
95 struct Stretch { | 104 static void get_stretch(const GrCaps& caps, int width, int height, |
96 enum Type { | 105 const GrTextureParams& params, SkGrStretch* stretch) { |
97 kNone_Type, | 106 stretch->fType = SkGrStretch::kNone_Type; |
98 kBilerp_Type, | |
99 kNearest_Type | |
100 } fType; | |
101 int fWidth; | |
102 int fHeight; | |
103 }; | |
104 | |
105 static void get_stretch(const GrContext* ctx, int width, int height, | |
106 const GrTextureParams* params, Stretch* stretch) { | |
107 stretch->fType = Stretch::kNone_Type; | |
108 bool doStretch = false; | 107 bool doStretch = false; |
109 if (params && params->isTiled() && !ctx->caps()->npotTextureTileSupport() && | 108 if (params.isTiled() && !caps.npotTextureTileSupport() && |
110 (!SkIsPow2(width) || !SkIsPow2(height))) { | 109 (!SkIsPow2(width) || !SkIsPow2(height))) { |
111 doStretch = true; | 110 doStretch = true; |
112 stretch->fWidth = GrNextPow2(SkTMax(width, ctx->caps()->minTextureSize(
))); | 111 stretch->fWidth = GrNextPow2(SkTMax(width, caps.minTextureSize())); |
113 stretch->fHeight = GrNextPow2(SkTMax(height, ctx->caps()->minTextureSize
())); | 112 stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize())); |
114 } else if (width < ctx->caps()->minTextureSize() || height < ctx->caps()->mi
nTextureSize()) { | 113 } else if (width < caps.minTextureSize() || height < caps.minTextureSize())
{ |
115 // The small texture issues appear to be with tiling. Hence it seems ok
to scale them | 114 // The small texture issues appear to be with tiling. Hence it seems ok
to scale them |
116 // up using the GPU. If issues persist we may need to CPU-stretch. | 115 // up using the GPU. If issues persist we may need to CPU-stretch. |
117 doStretch = true; | 116 doStretch = true; |
118 stretch->fWidth = SkTMax(width, ctx->caps()->minTextureSize()); | 117 stretch->fWidth = SkTMax(width, caps.minTextureSize()); |
119 stretch->fHeight = SkTMax(height, ctx->caps()->minTextureSize()); | 118 stretch->fHeight = SkTMax(height, caps.minTextureSize()); |
120 } | 119 } |
121 if (doStretch) { | 120 if (doStretch) { |
122 if (params) { | 121 switch(params.filterMode()) { |
123 switch(params->filterMode()) { | 122 case GrTextureParams::kNone_FilterMode: |
124 case GrTextureParams::kNone_FilterMode: | 123 stretch->fType = SkGrStretch::kNearest_Type; |
125 stretch->fType = Stretch::kNearest_Type; | 124 break; |
126 break; | 125 case GrTextureParams::kBilerp_FilterMode: |
127 case GrTextureParams::kBilerp_FilterMode: | 126 case GrTextureParams::kMipMap_FilterMode: |
128 case GrTextureParams::kMipMap_FilterMode: | 127 stretch->fType = SkGrStretch::kBilerp_Type; |
129 stretch->fType = Stretch::kBilerp_Type; | 128 break; |
130 break; | |
131 } | |
132 } else { | |
133 stretch->fType = Stretch::kBilerp_Type; | |
134 } | 129 } |
135 } else { | 130 } else { |
136 stretch->fWidth = -1; | 131 stretch->fWidth = -1; |
137 stretch->fHeight = -1; | 132 stretch->fHeight = -1; |
138 stretch->fType = Stretch::kNone_Type; | 133 stretch->fType = SkGrStretch::kNone_Type; |
139 } | 134 } |
140 } | 135 } |
141 | 136 |
142 static bool make_stretched_key(const GrUniqueKey& origKey, const Stretch& stretc
h, | 137 bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch, |
143 GrUniqueKey* stretchedKey) { | 138 GrUniqueKey* stretchedKey) { |
144 if (origKey.isValid() && Stretch::kNone_Type != stretch.fType) { | 139 if (origKey.isValid() && SkGrStretch::kNone_Type != stretch.fType) { |
145 uint32_t width = SkToU16(stretch.fWidth); | 140 uint32_t width = SkToU16(stretch.fWidth); |
146 uint32_t height = SkToU16(stretch.fHeight); | 141 uint32_t height = SkToU16(stretch.fHeight); |
147 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; | 142 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; |
148 GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2); | 143 GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2); |
149 builder[0] = stretch.fType; | 144 builder[0] = stretch.fType; |
150 builder[1] = width | (height << 16); | 145 builder[1] = width | (height << 16); |
151 builder.finish(); | 146 builder.finish(); |
152 return true; | 147 return true; |
153 } | 148 } |
154 SkASSERT(!stretchedKey->isValid()); | 149 SkASSERT(!stretchedKey->isValid()); |
155 return false; | 150 return false; |
156 } | 151 } |
157 | 152 |
158 static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRe
ct& subset) { | 153 static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRe
ct& subset, bool isMipMapped = false) { |
159 SkASSERT(SkIsU16(subset.width())); | 154 SkASSERT(SkIsU16(subset.width())); |
160 SkASSERT(SkIsU16(subset.height())); | 155 SkASSERT(SkIsU16(subset.height())); |
161 | 156 |
162 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 157 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
163 GrUniqueKey::Builder builder(key, kDomain, 4); | 158 GrUniqueKey::Builder builder(key, kDomain, 5); |
164 builder[0] = imageID; | 159 builder[0] = imageID; |
165 builder[1] = subset.x(); | 160 builder[1] = subset.x(); |
166 builder[2] = subset.y(); | 161 builder[2] = subset.y(); |
167 builder[3] = subset.width() | (subset.height() << 16); | 162 builder[3] = subset.width() | (subset.height() << 16); |
| 163 builder[4] = isMipMapped; |
168 } | 164 } |
169 | 165 |
170 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
set, | 166 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
set, |
171 const GrCaps& caps, SkImageUsageType usage) { | 167 const GrCaps& caps, const GrTextureParams& params) { |
172 const Stretch::Type stretches[] = { | 168 SkGrStretch stretch; |
173 Stretch::kNone_Type, // kUntiled_SkImageUsageType | 169 get_stretch(caps, subset.width(), subset.height(), params, &stretch); |
174 Stretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType | 170 if (SkGrStretch::kNone_Type != stretch.fType) { |
175 Stretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType | |
176 }; | |
177 | |
178 const bool isPow2 = SkIsPow2(subset.width()) && SkIsPow2(subset.height()); | |
179 const bool needToStretch = !isPow2 && | |
180 usage != kUntiled_SkImageUsageType && | |
181 !caps.npotTextureTileSupport(); | |
182 | |
183 if (needToStretch) { | |
184 GrUniqueKey tmpKey; | 171 GrUniqueKey tmpKey; |
185 make_unstretched_key(&tmpKey, imageID, subset); | 172 make_unstretched_key(&tmpKey, imageID, subset); |
186 | 173 if (!GrMakeStretchedKey(tmpKey, stretch, key)) { |
187 Stretch stretch; | 174 *key = tmpKey; |
188 stretch.fType = stretches[usage]; | |
189 stretch.fWidth = SkNextPow2(subset.width()); | |
190 stretch.fHeight = SkNextPow2(subset.height()); | |
191 if (!make_stretched_key(tmpKey, stretch, key)) { | |
192 goto UNSTRETCHED; | |
193 } | 175 } |
194 } else { | 176 } else { |
195 UNSTRETCHED: | |
196 make_unstretched_key(key, imageID, subset); | 177 make_unstretched_key(key, imageID, subset); |
197 } | 178 } |
198 } | 179 } |
199 | 180 |
200 static void make_image_keys(uint32_t imageID, const SkIRect& subset, const Stret
ch& stretch, | 181 static void make_image_keys(uint32_t imageID, const SkIRect& subset, const SkGrS
tretch& stretch, |
201 GrUniqueKey* key, GrUniqueKey* stretchedKey) { | 182 GrUniqueKey* key, GrUniqueKey* stretchedKey) { |
202 make_unstretched_key(key, imageID, subset); | 183 make_unstretched_key(key, imageID, subset); |
203 if (Stretch::kNone_Type != stretch.fType) { | 184 if (SkGrStretch::kNone_Type != stretch.fType) { |
204 make_stretched_key(*key, stretch, stretchedKey); | 185 GrMakeStretchedKey(*key, stretch, stretchedKey); |
205 } | 186 } |
206 } | 187 } |
207 | 188 |
208 GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { | 189 GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { |
209 GrSurfaceDesc desc; | 190 GrSurfaceDesc desc; |
210 desc.fFlags = kNone_GrSurfaceFlags; | 191 desc.fFlags = kNone_GrSurfaceFlags; |
211 desc.fWidth = info.width(); | 192 desc.fWidth = info.width(); |
212 desc.fHeight = info.height(); | 193 desc.fHeight = info.height(); |
213 desc.fConfig = SkImageInfo2GrPixelConfig(info); | 194 desc.fConfig = SkImageInfo2GrPixelConfig(info); |
214 desc.fSampleCnt = 0; | 195 desc.fSampleCnt = 0; |
215 return desc; | 196 return desc; |
216 } | 197 } |
217 | 198 |
218 namespace { | 199 namespace { |
219 | 200 |
220 // When the SkPixelRef genID changes, invalidate a corresponding GrResource desc
ribed by key. | 201 // When the SkPixelRef genID changes, invalidate a corresponding GrResource desc
ribed by key. |
221 class BitmapInvalidator : public SkPixelRef::GenIDChangeListener { | 202 class BitmapInvalidator : public SkPixelRef::GenIDChangeListener { |
222 public: | 203 public: |
223 explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {} | 204 explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {} |
224 private: | 205 private: |
225 GrUniqueKeyInvalidatedMessage fMsg; | 206 GrUniqueKeyInvalidatedMessage fMsg; |
226 | 207 |
227 void onChange() override { | 208 void onChange() override { |
228 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); | 209 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); |
229 } | 210 } |
230 }; | 211 }; |
231 | 212 |
232 } // namespace | 213 } // namespace |
233 | 214 |
| 215 static void add_key_and_invalidation_listener(GrContext* ctx, |
| 216 const GrUniqueKey& optionalKey, |
| 217 SkPixelRef* pixelRefForInvalidatio
nNotification, |
| 218 GrTexture& result) { |
| 219 if (optionalKey.isValid()) { |
| 220 if (pixelRefForInvalidationNotification) { |
| 221 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey); |
| 222 pixelRefForInvalidationNotification->addGenIDChangeListener(listener
); |
| 223 } |
| 224 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, &result); |
| 225 } |
| 226 } |
234 | 227 |
235 GrTexture* GrCreateTextureForPixels(GrContext* ctx, | 228 GrTexture* GrCreateTextureForPixels(GrContext* ctx, |
236 const GrUniqueKey& optionalKey, | 229 const GrUniqueKey& optionalKey, |
237 GrSurfaceDesc desc, | 230 GrSurfaceDesc desc, |
238 SkPixelRef* pixelRefForInvalidationNotificat
ion, | 231 SkPixelRef* pixelRefForInvalidationNotificat
ion, |
239 const void* pixels, | 232 const void* pixels, |
240 size_t rowBytes) { | 233 size_t rowBytes) { |
241 GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels
, rowBytes); | 234 GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels
, rowBytes); |
242 if (result && optionalKey.isValid()) { | 235 if (result) { |
243 if (pixelRefForInvalidationNotification) { | 236 add_key_and_invalidation_listener(ctx, optionalKey, pixelRefForInvalidat
ionNotification, |
244 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey); | 237 *result); |
245 pixelRefForInvalidationNotification->addGenIDChangeListener(listener
); | |
246 } | |
247 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result); | |
248 } | 238 } |
249 return result; | 239 return result; |
250 } | 240 } |
251 | 241 |
| 242 GrTexture* GrCreateTextureForPixels(GrContext* ctx, |
| 243 const GrUniqueKey& optionalKey, |
| 244 GrSurfaceDesc desc, |
| 245 SkPixelRef* pixelRefForInvalidationNotificat
ion, |
| 246 const SkTArray<SkMipMapLevel>& texels) { |
| 247 GrTexture* result = ctx->textureProvider()->createTexture(desc, true, texels
); |
| 248 if (result) { |
| 249 add_key_and_invalidation_listener(ctx, optionalKey, pixelRefForInvalidat
ionNotification, |
| 250 *result); |
| 251 } |
| 252 return result; |
| 253 } |
| 254 |
252 // creates a new texture that is the input texture scaled up. If optionalKey is
valid it will be | 255 // creates a new texture that is the input texture scaled up. If optionalKey is
valid it will be |
253 // set on the new texture. stretch controls whether the scaling is done using ne
arest or bilerp | 256 // set on the new texture. stretch controls whether the scaling is done using ne
arest or bilerp |
254 // filtering and the size to stretch the texture to. | 257 // filtering and the size to stretch the texture to. |
255 GrTexture* stretch_texture(GrTexture* inputTexture, const Stretch& stretch, | 258 GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch, |
256 SkPixelRef* pixelRef, | 259 SkPixelRef* pixelRef, |
257 const GrUniqueKey& optionalKey) { | 260 const GrUniqueKey& optionalKey) { |
258 SkASSERT(Stretch::kNone_Type != stretch.fType); | 261 SkASSERT(SkGrStretch::kNone_Type != stretch.fType); |
259 | 262 |
260 GrContext* context = inputTexture->getContext(); | 263 GrContext* context = inputTexture->getContext(); |
261 SkASSERT(context); | 264 SkASSERT(context); |
262 const GrCaps* caps = context->caps(); | 265 const GrCaps* caps = context->caps(); |
263 | 266 |
264 // Either it's a cache miss or the original wasn't cached to begin with. | 267 // Either it's a cache miss or the original wasn't cached to begin with. |
265 GrSurfaceDesc rtDesc = inputTexture->desc(); | 268 GrSurfaceDesc rtDesc = inputTexture->desc(); |
266 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; | 269 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; |
267 rtDesc.fWidth = stretch.fWidth; | 270 rtDesc.fWidth = stretch.fWidth; |
268 rtDesc.fHeight = stretch.fHeight; | 271 rtDesc.fHeight = stretch.fHeight; |
(...skipping 25 matching lines...) Expand all Loading... |
294 SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optional
Key, rtDesc, | 297 SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optional
Key, rtDesc, |
295 pixelRef, nullptr
,0)); | 298 pixelRef, nullptr
,0)); |
296 if (!stretched) { | 299 if (!stretched) { |
297 return nullptr; | 300 return nullptr; |
298 } | 301 } |
299 GrPaint paint; | 302 GrPaint paint; |
300 | 303 |
301 // If filtering is not desired then we want to ensure all texels in the resa
mpled image are | 304 // If filtering is not desired then we want to ensure all texels in the resa
mpled image are |
302 // copies of texels from the original. | 305 // copies of texels from the original. |
303 GrTextureParams params(SkShader::kClamp_TileMode, | 306 GrTextureParams params(SkShader::kClamp_TileMode, |
304 Stretch::kBilerp_Type == stretch.fType ? | 307 SkGrStretch::kBilerp_Type == stretch.fType ? |
305 GrTextureParams::kBilerp_FilterMode : | 308 GrTextureParams::kBilerp_FilterMode : |
306 GrTextureParams::kNone_FilterMode); | 309 GrTextureParams::kNone_FilterMode); |
307 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params); | 310 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params); |
308 | 311 |
309 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtD
esc.fHeight)); | 312 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtD
esc.fHeight)); |
310 SkRect localRect = SkRect::MakeWH(1.f, 1.f); | 313 SkRect localRect = SkRect::MakeWH(1.f, 1.f); |
311 | 314 |
312 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext()); | 315 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(stretched->asRe
nderTarget())); |
313 if (!drawContext) { | 316 if (!drawContext) { |
314 return nullptr; | 317 return nullptr; |
315 } | 318 } |
316 | 319 |
317 drawContext->drawNonAARectToRect(stretched->asRenderTarget(), GrClip::WideOp
en(), paint, | 320 drawContext->drawNonAARectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), r
ect, localRect); |
318 SkMatrix::I(), rect, localRect); | |
319 | 321 |
320 return stretched.detach(); | 322 return stretched.detach(); |
321 } | 323 } |
322 | 324 |
323 GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data, | 325 GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data, |
324 int expectedW, int expectedH, | 326 int expectedW, int expectedH, |
325 const void** outStartOfDataToUp
load) { | 327 const void** outStartOfDataToUp
load) { |
326 *outStartOfDataToUpload = nullptr; | 328 *outStartOfDataToUpload = nullptr; |
327 #ifndef SK_IGNORE_ETC1_SUPPORT | 329 #ifndef SK_IGNORE_ETC1_SUPPORT |
328 if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) { | 330 if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 GrTexture* texture = provider.refAsTexture(ctx, desc, useCache); | 416 GrTexture* texture = provider.refAsTexture(ctx, desc, useCache); |
415 if (!texture) { | 417 if (!texture) { |
416 return nullptr; | 418 return nullptr; |
417 } | 419 } |
418 | 420 |
419 if (useCache) { | 421 if (useCache) { |
420 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey); | 422 BitmapInvalidator* listener = new BitmapInvalidator(optionalKey); |
421 pixelRef->addGenIDChangeListener(listener); | 423 pixelRef->addGenIDChangeListener(listener); |
422 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, texture); | 424 ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, texture); |
423 } | 425 } |
424 return texture; | 426 return texture; |
425 } | 427 } |
426 | 428 |
427 static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx, | 429 static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx, |
428 const SkBitmap& origBitmap, | 430 const SkBitmap& origBitmap, |
429 const GrUniqueKey& optionalK
ey) { | 431 const GrUniqueKey& optionalK
ey) { |
430 if (origBitmap.width() < ctx->caps()->minTextureSize() || | 432 if (origBitmap.width() < ctx->caps()->minTextureSize() || |
431 origBitmap.height() < ctx->caps()->minTextureSize()) { | 433 origBitmap.height() < ctx->caps()->minTextureSize()) { |
432 return nullptr; | 434 return nullptr; |
433 } | 435 } |
434 SkBitmap tmpBitmap; | 436 SkBitmap tmpBitmap; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 | 475 |
474 SkAutoLockPixels alp(*bitmap); | 476 SkAutoLockPixels alp(*bitmap); |
475 if (!bitmap->readyToDraw()) { | 477 if (!bitmap->readyToDraw()) { |
476 return nullptr; | 478 return nullptr; |
477 } | 479 } |
478 | 480 |
479 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(
), | 481 return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(
), |
480 bitmap->getPixels(), bitmap->rowBytes()); | 482 bitmap->getPixels(), bitmap->rowBytes()); |
481 } | 483 } |
482 | 484 |
483 static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const Stretch& stretch) { | 485 static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const SkGrStretch& stretch)
{ |
484 SkBitmap stretched; | 486 SkBitmap stretched; |
485 stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight); | 487 stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight); |
486 SkCanvas canvas(stretched); | 488 SkCanvas canvas(stretched); |
487 SkPaint paint; | 489 SkPaint paint; |
488 switch (stretch.fType) { | 490 switch (stretch.fType) { |
489 case Stretch::kNearest_Type: | 491 case SkGrStretch::kNearest_Type: |
490 paint.setFilterQuality(kNone_SkFilterQuality); | 492 paint.setFilterQuality(kNone_SkFilterQuality); |
491 break; | 493 break; |
492 case Stretch::kBilerp_Type: | 494 case SkGrStretch::kBilerp_Type: |
493 paint.setFilterQuality(kLow_SkFilterQuality); | 495 paint.setFilterQuality(kLow_SkFilterQuality); |
494 break; | 496 break; |
495 case Stretch::kNone_Type: | 497 case SkGrStretch::kNone_Type: |
496 SkDEBUGFAIL("Shouldn't get here."); | 498 SkDEBUGFAIL("Shouldn't get here."); |
497 break; | 499 break; |
498 } | 500 } |
499 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar
(stretch.fHeight)); | 501 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar
(stretch.fHeight)); |
500 canvas.drawBitmapRect(bmp, dstRect, &paint); | 502 canvas.drawBitmapRect(bmp, dstRect, &paint); |
501 return stretched; | 503 return stretched; |
502 } | 504 } |
503 | 505 |
504 static GrTexture* create_bitmap_texture(GrContext* ctx, | |
505 const SkBitmap& bmp, | |
506 const Stretch& stretch, | |
507 const GrUniqueKey& unstretchedKey, | |
508 const GrUniqueKey& stretchedKey) { | |
509 if (Stretch::kNone_Type != stretch.fType) { | |
510 SkAutoTUnref<GrTexture> unstretched; | |
511 // Check if we have the unstretched version in the cache, if not create
it. | |
512 if (unstretchedKey.isValid()) { | |
513 unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueK
ey(unstretchedKey)); | |
514 } | |
515 if (!unstretched) { | |
516 unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstre
tchedKey)); | |
517 if (!unstretched) { | |
518 // We might not have been able to create a unstrecthed texture b
ecause it is smaller | |
519 // than the min texture size. In that case do cpu stretching. | |
520 SkBitmap stretchedBmp = stretch_on_cpu(bmp, stretch); | |
521 return create_unstretched_bitmap_texture(ctx, stretchedBmp, stre
tchedKey); | |
522 } | |
523 } | |
524 return stretch_texture(unstretched, stretch, bmp.pixelRef(), stretchedKe
y); | |
525 } | |
526 return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey); | |
527 } | |
528 | |
529 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub
set, | 506 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub
set, |
530 GrTexture* nativeTexture, const GrTextureParams* params) { | 507 GrTexture* nativeTexture, const GrTextureParams& params) { |
531 Stretch stretch; | 508 SkGrStretch stretch; |
532 get_stretch(ctx, subset.width(), subset.height(), params, &stretch); | 509 get_stretch(*ctx->caps(), subset.width(), subset.height(), params, &stretch)
; |
533 | 510 |
534 // Handle the case where the bitmap/image is explicitly texture backed. | 511 // Handle the case where the bitmap/image is explicitly texture backed. |
535 if (nativeTexture) { | 512 if (nativeTexture) { |
536 if (Stretch::kNone_Type == stretch.fType) { | 513 if (SkGrStretch::kNone_Type == stretch.fType) { |
537 return true; | 514 return true; |
538 } | 515 } |
539 const GrUniqueKey& key = nativeTexture->getUniqueKey(); | 516 const GrUniqueKey& key = nativeTexture->getUniqueKey(); |
540 if (!key.isValid()) { | 517 if (!key.isValid()) { |
541 return false; | 518 return false; |
542 } | 519 } |
543 GrUniqueKey stretchedKey; | 520 GrUniqueKey stretchedKey; |
544 make_stretched_key(key, stretch, &stretchedKey); | 521 GrMakeStretchedKey(key, stretch, &stretchedKey); |
545 return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey); | 522 return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey); |
546 } | 523 } |
547 | 524 |
548 GrUniqueKey key, stretchedKey; | 525 GrUniqueKey key, stretchedKey; |
549 make_image_keys(imageID, subset, stretch, &key, &stretchedKey); | 526 make_image_keys(imageID, subset, stretch, &key, &stretchedKey); |
550 return ctx->textureProvider()->existsTextureWithUniqueKey( | 527 return ctx->textureProvider()->existsTextureWithUniqueKey( |
551 (Stretch::kNone_Type == stretch.fType) ? key : stretchedKey); | 528 (SkGrStretch::kNone_Type == stretch.fType) ? key : stretchedKey); |
552 } | 529 } |
553 | 530 |
554 bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap, | 531 static GrTexture* generate_mipmaps(const SkBitmap& bitmap, |
555 const GrTextureParams* params) { | 532 GrContext* ctx) { |
556 if (bitmap.isVolatile()) { | 533 // Make sure the value of the int fits inside a uint32_t |
557 return false; // we don't cache volatile bitmaps. | 534 if (bitmap.width() <= 0 && bitmap.height() <= 0) { |
| 535 return nullptr; |
558 } | 536 } |
559 return GrIsImageInCache(ctx, bitmap.getGenerationID(), bitmap.getSubset(), b
itmap.getTexture(), | 537 SkASSERT(sizeof(int) <= sizeof(uint32_t)); |
560 params); | 538 const uint32_t baseWidth = static_cast<uint32_t>(bitmap.width()); |
| 539 const uint32_t baseHeight = static_cast<uint32_t>(bitmap.height()); |
| 540 |
| 541 // OpenGL's spec requires that each mipmap level has height/width equal to |
| 542 // max(1, floor(original_height / 2^i) |
| 543 // (or original_height) where i is the mipmap level. |
| 544 // Keep scaling down until both axes are size 1. |
| 545 |
| 546 const uint32_t largestAxis = SkTMax(baseWidth, baseHeight); |
| 547 const int leadingZeros = SkCLZ(largestAxis); |
| 548 // If the value 00011010 has 3 leading 0s, it has 5 significant bits |
| 549 // (the bits which are not leading zeros) |
| 550 const int significantBits = (sizeof(uint32_t) * 8) - leadingZeros; |
| 551 if (significantBits < 0) |
| 552 { |
| 553 return nullptr; |
| 554 } |
| 555 const uint32_t unsignedSignificantBits = static_cast<uint32_t>(significantBi
ts); |
| 556 const uint32_t mipLevelCount = unsignedSignificantBits; |
| 557 |
| 558 GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info()); |
| 559 const bool isMipMapped = mipLevelCount > 1; |
| 560 desc.fIsMipMapped = isMipMapped; |
| 561 |
| 562 /* |
| 563 SkAutoPixmapUnlock srcUnlocker; |
| 564 if (!bitmap.requestLock(&srcUnlocker)) { |
| 565 return nullptr; |
| 566 } |
| 567 const SkPixmap& srcPixmap = srcUnlocker.pixmap(); |
| 568 if (nullptr == srcPixmap.addr()) { |
| 569 return nullptr; |
| 570 } |
| 571 */ |
| 572 |
| 573 SkTArray<SkMipMapLevel> texels(mipLevelCount); |
| 574 //SkMipMapLevel baseLevel(srcPixmap.addr(), bitmap.rowBytes(), baseWidth, ba
seHeight); |
| 575 SkMipMapLevel baseLevel(bitmap.getPixels(), bitmap.rowBytes(), baseWidth, ba
seHeight); |
| 576 texels.push_back(baseLevel); |
| 577 |
| 578 SkTArray<SkBitmap> mipLevelBitmaps(mipLevelCount - 1); |
| 579 mipLevelBitmaps.push_back_n(mipLevelCount - 1); |
| 580 |
| 581 for (uint32_t i = 1; i < mipLevelCount; i++) { |
| 582 SkBitmap& currentMipBitmap = mipLevelBitmaps[i - 1]; |
| 583 |
| 584 uint32_t twoToTheMipLevel = 1 << (i + 1); |
| 585 uint32_t currentMipLevelWidth = SkTMax(1u, baseWidth / twoToTheMipLevel)
; |
| 586 uint32_t currentMipLevelHeight = SkTMax(1u, baseHeight / twoToTheMipLeve
l); |
| 587 |
| 588 SkImageInfo info = SkImageInfo::Make(currentMipLevelWidth, currentMipLev
elHeight, |
| 589 currentMipBitmap.colorType(), |
| 590 bitmap.alphaType()); |
| 591 if (!currentMipBitmap.tryAllocPixels(info)) |
| 592 { |
| 593 return nullptr; |
| 594 } |
| 595 |
| 596 SkCanvas canvas(currentMipBitmap); |
| 597 canvas.clear(SK_ColorTRANSPARENT); |
| 598 canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0)); |
| 599 |
| 600 /* |
| 601 SkAutoPixmapUnlock mipUnlocker; |
| 602 if (!currentMipBitmap.requestLock(&mipUnlocker)) { |
| 603 return nullptr; |
| 604 } |
| 605 const SkPixmap& mipPixmap = mipUnlocker.pixmap(); |
| 606 if (nullptr == mipPixmap.addr()) { |
| 607 return nullptr; |
| 608 } |
| 609 */ |
| 610 |
| 611 SkMipMapLevel currentMipLevel(currentMipBitmap.getPixels(), |
| 612 //SkMipMapLevel currentMipLevel(mipPixmap.addr(), |
| 613 currentMipBitmap.rowBytes(), |
| 614 currentMipLevelWidth, currentMipLevelHeigh
t); |
| 615 texels.push_back(currentMipLevel); |
| 616 } |
| 617 |
| 618 |
| 619 GrUniqueKey unstretchedKey; |
| 620 make_unstretched_key(&unstretchedKey, bitmap.getGenerationID(), bitmap.getSu
bset(), isMipMapped); |
| 621 |
| 622 return GrCreateTextureForPixels(ctx, unstretchedKey, desc, bitmap.pixelRef()
, texels); |
561 } | 623 } |
562 | 624 |
563 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, | |
564 const SkBitmap& bitmap, | |
565 const GrTextureParams* params) { | |
566 | 625 |
567 Stretch stretch; | 626 class Bitmap_GrTextureMaker : public GrTextureMaker { |
568 get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch); | 627 public: |
| 628 Bitmap_GrTextureMaker(const SkBitmap& bitmap) |
| 629 : INHERITED(bitmap.width(), bitmap.height()) |
| 630 , fBitmap(bitmap) |
| 631 {} |
569 | 632 |
570 GrTexture* result = bitmap.getTexture(); | 633 protected: |
571 if (result) { | 634 GrTexture* onRefUnstretchedTexture(GrContext* ctx, const GrTextureParams* pa
rams) override { |
572 if (Stretch::kNone_Type == stretch.fType) { | 635 GrTexture* texture = fBitmap.getTexture(); |
573 return SkRef(result); | 636 |
| 637 if (params && params->filterMode() == GrTextureParams::kMipMap_FilterMod
e) { |
| 638 return generate_mipmaps(fBitmap, ctx); |
574 } | 639 } |
575 GrUniqueKey stretchedKey; | 640 |
576 // Don't create a key for the resized version if the bmp is volatile. | 641 if (texture) { |
577 if (!bitmap.isVolatile()) { | 642 return SkRef(texture); |
578 const GrUniqueKey& key = result->getUniqueKey(); | |
579 if (key.isValid()) { | |
580 make_stretched_key(key, stretch, &stretchedKey); | |
581 GrTexture* stretched = | |
582 ctx->textureProvider()->findAndRefTextureByUniqueKey(stretch
edKey); | |
583 if (stretched) { | |
584 return stretched; | |
585 } | |
586 } | |
587 } | 643 } |
588 return stretch_texture(result, stretch, bitmap.pixelRef(), stretchedKey)
; | |
589 } | |
590 | 644 |
591 GrUniqueKey key, resizedKey; | 645 GrUniqueKey unstretchedKey; |
| 646 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap
.getSubset()); |
592 | 647 |
593 if (!bitmap.isVolatile()) { | 648 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(unstretchedKey); |
594 // If the bitmap isn't changing try to find a cached copy first. | |
595 make_image_keys(bitmap.getGenerationID(), bitmap.getSubset(), stretch, &
key, &resizedKey); | |
596 | |
597 result = ctx->textureProvider()->findAndRefTextureByUniqueKey( | |
598 resizedKey.isValid() ? resizedKey : key); | |
599 if (result) { | 649 if (result) { |
600 return result; | 650 return result; |
601 } | 651 } |
| 652 return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey); |
602 } | 653 } |
603 | 654 |
604 result = create_bitmap_texture(ctx, bitmap, stretch, key, resizedKey); | 655 bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKe
y) override { |
605 if (result) { | 656 if (fBitmap.isVolatile()) { |
606 return result; | 657 return false; |
| 658 } |
| 659 |
| 660 GrUniqueKey unstretchedKey; |
| 661 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap
.getSubset()); |
| 662 return GrMakeStretchedKey(unstretchedKey, stretch, stretchedKey); |
607 } | 663 } |
608 | 664 |
609 SkErrorInternals::SetError( kInternalError_SkError, | 665 void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { |
610 "---- failed to create texture for cache [%d %d]
\n", | 666 fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretch
edKey)); |
611 bitmap.width(), bitmap.height()); | 667 } |
612 | 668 |
613 return nullptr; | 669 bool onGetROBitmap(SkBitmap* bitmap) override { |
614 } | 670 *bitmap = fBitmap; |
| 671 return true; |
| 672 } |
615 | 673 |
616 // TODO: make this be the canonical signature, and turn the version that takes G
rTextureParams* | 674 private: |
617 // into a wrapper that contains the inverse of these tables. | 675 const SkBitmap fBitmap; |
618 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, | |
619 const SkBitmap& bitmap, | |
620 SkImageUsageType usage) { | |
621 // Just need a params that will trigger the correct cache key / etc, since t
he usage doesn't | |
622 // tell us the specifics about filter level or specific tiling. | |
623 | 676 |
624 const SkShader::TileMode tiles[] = { | 677 typedef GrTextureMaker INHERITED; |
625 SkShader::kClamp_TileMode, // kUntiled_SkImageUsageType | 678 }; |
626 SkShader::kRepeat_TileMode, // kTiled_Unfiltered_SkImageUsageType | |
627 SkShader::kRepeat_TileMode, // kTiled_Filtered_SkImageUsageType | |
628 }; | |
629 | 679 |
630 const GrTextureParams::FilterMode filters[] = { | 680 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, |
631 GrTextureParams::kNone_FilterMode, // kUntiled_SkImageUsageType | 681 const GrTextureParams& params) { |
632 GrTextureParams::kNone_FilterMode, // kTiled_Unfiltered_SkImageUsag
eType | 682 return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params); |
633 GrTextureParams::kBilerp_FilterMode, // kTiled_Filtered_SkImageUsageT
ype | |
634 }; | |
635 | |
636 GrTextureParams params(tiles[usage], filters[usage]); | |
637 return GrRefCachedBitmapTexture(ctx, bitmap, ¶ms); | |
638 } | 683 } |
639 | 684 |
640 /////////////////////////////////////////////////////////////////////////////// | 685 /////////////////////////////////////////////////////////////////////////////// |
641 | 686 |
642 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass | 687 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass |
643 // alpha info, that will be considered. | 688 // alpha info, that will be considered. |
644 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf
ileType pt) { | 689 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf
ileType pt) { |
645 switch (ct) { | 690 switch (ct) { |
646 case kUnknown_SkColorType: | 691 case kUnknown_SkColorType: |
647 return kUnknown_GrPixelConfig; | 692 return kUnknown_GrPixelConfig; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 } | 744 } |
700 if (ctOut) { | 745 if (ctOut) { |
701 *ctOut = ct; | 746 *ctOut = ct; |
702 } | 747 } |
703 if (ptOut) { | 748 if (ptOut) { |
704 *ptOut = pt; | 749 *ptOut = pt; |
705 } | 750 } |
706 return true; | 751 return true; |
707 } | 752 } |
708 | 753 |
709 /////////////////////////////////////////////////////////////////////////////// | |
710 | 754 |
711 bool SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor
paintColor, | 755 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
712 bool constantColor, GrPaint* grPaint) { | |
713 | 756 |
| 757 static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primi
tiveIsSrc) { |
| 758 if (primitiveIsSrc) { |
| 759 return SkXfermode::kSrc_Mode != mode; |
| 760 } else { |
| 761 return SkXfermode::kDst_Mode != mode; |
| 762 } |
| 763 } |
| 764 |
| 765 static inline bool skpaint_to_grpaint_impl(GrContext* context, |
| 766 const SkPaint& skPaint, |
| 767 const SkMatrix& viewM, |
| 768 const GrFragmentProcessor** shaderPro
cessor, |
| 769 SkXfermode::Mode* primColorMode, |
| 770 bool primitiveIsSrc, |
| 771 GrPaint* grPaint) { |
714 grPaint->setAntiAlias(skPaint.isAntiAlias()); | 772 grPaint->setAntiAlias(skPaint.isAntiAlias()); |
715 | 773 |
| 774 // Setup the initial color considering the shader, the SkPaint color, and th
e presence or not |
| 775 // of per-vertex colors. |
| 776 SkAutoTUnref<const GrFragmentProcessor> aufp; |
| 777 const GrFragmentProcessor* shaderFP = nullptr; |
| 778 if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc))
{ |
| 779 if (shaderProcessor) { |
| 780 shaderFP = *shaderProcessor; |
| 781 } else if (const SkShader* shader = skPaint.getShader()) { |
| 782 aufp.reset(shader->asFragmentProcessor(context, viewM, nullptr, |
| 783 skPaint.getFilterQuality())); |
| 784 shaderFP = aufp; |
| 785 if (!shaderFP) { |
| 786 return false; |
| 787 } |
| 788 } |
| 789 } |
| 790 |
| 791 // Set this in below cases if the output of the shader/paint-color/paint-alp
ha/primXfermode is |
| 792 // a known constant value. In that case we can simply apply a color filter d
uring this |
| 793 // conversion without converting the color filter to a GrFragmentProcessor. |
| 794 bool applyColorFilterToPaintColor = false; |
| 795 if (shaderFP) { |
| 796 if (primColorMode) { |
| 797 // There is a blend between the primitive color and the shader color
. The shader sees |
| 798 // the opaque paint color. The shader's output is blended using the
provided mode by |
| 799 // the primitive color. The blended color is then modulated by the p
aint's alpha. |
| 800 |
| 801 // The geometry processor will insert the primitive color to start t
he color chain, so |
| 802 // the GrPaint color will be ignored. |
| 803 |
| 804 GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor()); |
| 805 |
| 806 shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput)
; |
| 807 aufp.reset(shaderFP); |
| 808 |
| 809 if (primitiveIsSrc) { |
| 810 shaderFP = GrXfermodeFragmentProcessor::CreateFromDstProcessor(s
haderFP, |
| 811 *
primColorMode); |
| 812 } else { |
| 813 shaderFP = GrXfermodeFragmentProcessor::CreateFromSrcProcessor(s
haderFP, |
| 814 *
primColorMode); |
| 815 } |
| 816 aufp.reset(shaderFP); |
| 817 // The above may return null if compose results in a pass through of
the prim color. |
| 818 if (shaderFP) { |
| 819 grPaint->addColorFragmentProcessor(shaderFP); |
| 820 } |
| 821 |
| 822 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor()); |
| 823 if (GrColor_WHITE != paintAlpha) { |
| 824 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create
( |
| 825 paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))
->unref(); |
| 826 } |
| 827 } else { |
| 828 // The shader's FP sees the paint unpremul color |
| 829 grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor())); |
| 830 grPaint->addColorFragmentProcessor(shaderFP); |
| 831 } |
| 832 } else { |
| 833 if (primColorMode) { |
| 834 // There is a blend between the primitive color and the paint color.
The blend considers |
| 835 // the opaque paint color. The paint's alpha is applied to the post-
blended color. |
| 836 SkAutoTUnref<const GrFragmentProcessor> processor( |
| 837 GrConstColorProcessor::Create(SkColorToOpaqueGrColor(skPaint.get
Color()), |
| 838 GrConstColorProcessor::kIgnore_Inp
utMode)); |
| 839 if (primitiveIsSrc) { |
| 840 processor.reset(GrXfermodeFragmentProcessor::CreateFromDstProces
sor(processor, |
| 841
*primColorMode)); |
| 842 } else { |
| 843 processor.reset(GrXfermodeFragmentProcessor::CreateFromSrcProces
sor(processor, |
| 844
*primColorMode)); |
| 845 |
| 846 } |
| 847 if (processor) { |
| 848 grPaint->addColorFragmentProcessor(processor); |
| 849 } |
| 850 |
| 851 grPaint->setColor(SkColorToOpaqueGrColor(skPaint.getColor())); |
| 852 |
| 853 GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor()); |
| 854 if (GrColor_WHITE != paintAlpha) { |
| 855 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create
( |
| 856 paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))
->unref(); |
| 857 } |
| 858 } else { |
| 859 // No shader, no primitive color. |
| 860 grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor())); |
| 861 applyColorFilterToPaintColor = true; |
| 862 } |
| 863 } |
| 864 |
| 865 SkColorFilter* colorFilter = skPaint.getColorFilter(); |
| 866 if (colorFilter) { |
| 867 if (applyColorFilterToPaintColor) { |
| 868 grPaint->setColor(SkColorToPremulGrColor(colorFilter->filterColor(sk
Paint.getColor()))); |
| 869 } else { |
| 870 SkAutoTUnref<const GrFragmentProcessor> cfFP( |
| 871 colorFilter->asFragmentProcessor(context)); |
| 872 if (cfFP) { |
| 873 grPaint->addColorFragmentProcessor(cfFP); |
| 874 } else { |
| 875 return false; |
| 876 } |
| 877 } |
| 878 } |
| 879 |
716 SkXfermode* mode = skPaint.getXfermode(); | 880 SkXfermode* mode = skPaint.getXfermode(); |
717 GrXPFactory* xpFactory = nullptr; | 881 GrXPFactory* xpFactory = nullptr; |
718 if (!SkXfermode::AsXPFactory(mode, &xpFactory)) { | 882 if (!SkXfermode::AsXPFactory(mode, &xpFactory)) { |
719 // Fall back to src-over | 883 // Fall back to src-over |
720 // return false here? | 884 // return false here? |
721 xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode); | 885 xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode); |
722 } | 886 } |
723 SkASSERT(xpFactory); | 887 SkASSERT(xpFactory); |
724 grPaint->setXPFactory(xpFactory)->unref(); | 888 grPaint->setXPFactory(xpFactory)->unref(); |
725 | 889 |
726 //set the color of the paint to the one of the parameter | |
727 grPaint->setColor(paintColor); | |
728 | |
729 SkColorFilter* colorFilter = skPaint.getColorFilter(); | |
730 if (colorFilter) { | |
731 // if the source color is a constant then apply the filter here once rat
her than per pixel | |
732 // in a shader. | |
733 if (constantColor) { | |
734 SkColor filtered = colorFilter->filterColor(skPaint.getColor()); | |
735 grPaint->setColor(SkColor2GrColor(filtered)); | |
736 } else { | |
737 SkTDArray<const GrFragmentProcessor*> array; | |
738 // return false if failed? | |
739 if (colorFilter->asFragmentProcessors(context, grPaint->getProcessor
DataManager(), | |
740 &array)) { | |
741 for (int i = 0; i < array.count(); ++i) { | |
742 grPaint->addColorFragmentProcessor(array[i]); | |
743 array[i]->unref(); | |
744 } | |
745 } | |
746 } | |
747 } | |
748 | |
749 #ifndef SK_IGNORE_GPU_DITHER | 890 #ifndef SK_IGNORE_GPU_DITHER |
750 if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) { | 891 if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) { |
751 grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref(); | 892 grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref(); |
752 } | 893 } |
753 #endif | 894 #endif |
754 return true; | 895 return true; |
755 } | 896 } |
756 | 897 |
757 bool SkPaint2GrPaint(GrContext* context,const SkPaint& skPaint, const SkMatrix&
viewM, | 898 bool SkPaintToGrPaint(GrContext* context, const SkPaint& skPaint, const SkMatrix
& viewM, |
758 bool constantColor, GrPaint* grPaint) { | 899 GrPaint* grPaint) { |
759 SkShader* shader = skPaint.getShader(); | 900 return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, fa
lse, grPaint); |
760 if (nullptr == shader) { | 901 } |
761 return SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint
.getColor()), | |
762 constantColor, grPaint); | |
763 } | |
764 | 902 |
765 GrColor paintColor = SkColor2GrColor(skPaint.getColor()); | 903 /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProce
ssor. */ |
766 | 904 bool SkPaintToGrPaintReplaceShader(GrContext* context, |
767 const GrFragmentProcessor* fp = shader->asFragmentProcessor(context, viewM,
NULL, | 905 const SkPaint& skPaint, |
768 skPaint.getFilterQuality(), grPaint->getProcessorDataManager()); | 906 const GrFragmentProcessor* shaderFP, |
769 if (!fp) { | 907 GrPaint* grPaint) { |
| 908 if (!shaderFP) { |
770 return false; | 909 return false; |
771 } | 910 } |
772 grPaint->addColorFragmentProcessor(fp)->unref(); | 911 return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), &shaderFP, n
ullptr, false, |
773 constantColor = false; | 912 grPaint); |
| 913 } |
774 | 914 |
775 // The grcolor is automatically set when calling asFragmentProcessor. | 915 /** Ignores the SkShader (if any) on skPaint. */ |
776 // If the shader can be seen as an effect it returns true and adds its effec
t to the grpaint. | 916 bool SkPaintToGrPaintNoShader(GrContext* context, |
777 return SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor,
grPaint); | 917 const SkPaint& skPaint, |
| 918 GrPaint* grPaint) { |
| 919 // Use a ptr to a nullptr to to indicate that the SkShader is ignored and no
t replaced. |
| 920 static const GrFragmentProcessor* kNullShaderFP = nullptr; |
| 921 static const GrFragmentProcessor** kIgnoreShader = &kNullShaderFP; |
| 922 return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), kIgnoreShade
r, nullptr, false, |
| 923 grPaint); |
778 } | 924 } |
779 | 925 |
| 926 /** Blends the SkPaint's shader (or color if no shader) with a per-primitive col
or which must |
| 927 be setup as a vertex attribute using the specified SkXfermode::Mode. */ |
| 928 bool SkPaintToGrPaintWithXfermode(GrContext* context, |
| 929 const SkPaint& skPaint, |
| 930 const SkMatrix& viewM, |
| 931 SkXfermode::Mode primColorMode, |
| 932 bool primitiveIsSrc, |
| 933 GrPaint* grPaint) { |
| 934 return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, &primColorM
ode, primitiveIsSrc, |
| 935 grPaint); |
| 936 } |
| 937 |
| 938 |
| 939 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
| 940 |
780 SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) { | 941 SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) { |
781 #ifdef SK_DEBUG | 942 #ifdef SK_DEBUG |
782 const GrSurfaceDesc& desc = tex->desc(); | 943 const GrSurfaceDesc& desc = tex->desc(); |
783 SkASSERT(w <= desc.fWidth); | 944 SkASSERT(w <= desc.fWidth); |
784 SkASSERT(h <= desc.fHeight); | 945 SkASSERT(h <= desc.fHeight); |
785 #endif | 946 #endif |
786 const GrPixelConfig config = tex->config(); | 947 const GrPixelConfig config = tex->config(); |
787 SkColorType ct; | 948 SkColorType ct; |
788 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; | 949 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; |
789 if (!GrPixelConfig2ColorAndProfileType(config, &ct, nullptr)) { | 950 if (!GrPixelConfig2ColorAndProfileType(config, &ct, nullptr)) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 SkErrorInternals::SetError( kInvalidPaint_SkError, | 994 SkErrorInternals::SetError( kInvalidPaint_SkError, |
834 "Sorry, I don't understand the filtering
" | 995 "Sorry, I don't understand the filtering
" |
835 "mode you asked for. Falling back to " | 996 "mode you asked for. Falling back to " |
836 "MIPMaps."); | 997 "MIPMaps."); |
837 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 998 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
838 break; | 999 break; |
839 | 1000 |
840 } | 1001 } |
841 return textureFilterMode; | 1002 return textureFilterMode; |
842 } | 1003 } |
| 1004 |
| 1005 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
| 1006 |
| 1007 GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParam
s& params) { |
| 1008 SkGrStretch stretch; |
| 1009 get_stretch(*ctx->caps(), this->width(), this->height(), params, &stretch); |
| 1010 |
| 1011 if (SkGrStretch::kNone_Type == stretch.fType) { |
| 1012 return this->onRefUnstretchedTexture(ctx, ¶ms); |
| 1013 } |
| 1014 |
| 1015 GrUniqueKey stretchedKey; |
| 1016 if (this->onMakeStretchedKey(stretch, &stretchedKey)) { |
| 1017 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(stretchedKey); |
| 1018 if (result) { |
| 1019 return result; |
| 1020 } |
| 1021 } |
| 1022 |
| 1023 GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch, ¶ms); |
| 1024 if (!result) { |
| 1025 return nullptr; |
| 1026 } |
| 1027 |
| 1028 if (stretchedKey.isValid()) { |
| 1029 ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result); |
| 1030 this->onNotifyStretchCached(stretchedKey); |
| 1031 } |
| 1032 return result; |
| 1033 } |
| 1034 |
| 1035 GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const SkGr
Stretch& stretch, const GrTextureParams* params) { |
| 1036 if (this->width() < ctx->caps()->minTextureSize() || |
| 1037 this->height() < ctx->caps()->minTextureSize()) |
| 1038 { |
| 1039 // we can't trust our ability to use HW to perform the stretch, so we re
quest |
| 1040 // a raster instead, and perform the stretch on the CPU. |
| 1041 SkBitmap bitmap; |
| 1042 if (!this->onGetROBitmap(&bitmap)) { |
| 1043 return nullptr; |
| 1044 } |
| 1045 SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch); |
| 1046 return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey(
)); |
| 1047 } else { |
| 1048 SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx, p
arams)); |
| 1049 if (!unstretched) { |
| 1050 return nullptr; |
| 1051 } |
| 1052 return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey()); |
| 1053 } |
| 1054 } |
OLD | NEW |