1 /*
2 * Copyright 2012 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 #include "include/core/SkBitmap.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkData.h"
11 #include "include/core/SkImageEncoder.h"
12 #include "include/core/SkImageFilter.h"
13 #include "include/core/SkImageGenerator.h"
14 #include "include/core/SkPicture.h"
15 #include "include/core/SkString.h"
16 #include "include/core/SkSurface.h"
17 #include "src/core/SkBitmapCache.h"
18 #include "src/core/SkCachedData.h"
19 #include "src/core/SkColorSpacePriv.h"
20 #include "src/core/SkImageFilterCache.h"
21 #include "src/core/SkImageFilter_Base.h"
22 #include "src/core/SkImagePriv.h"
23 #include "src/core/SkNextID.h"
24 #include "src/core/SkSpecialImage.h"
25 #include "src/image/SkImage_Base.h"
26 #include "src/image/SkReadPixelsRec.h"
27 #include "src/shaders/SkImageShader.h"
28
29 #if SK_SUPPORT_GPU
30 #include "include/gpu/GrContext.h"
31 #include "include/gpu/GrTexture.h"
32 #include "src/image/SkImage_Gpu.h"
33 #endif
34 #include "include/gpu/GrBackendSurface.h"
35
SkImage(const SkImageInfo & info,uint32_t uniqueID)36 SkImage::SkImage(const SkImageInfo& info, uint32_t uniqueID)
37 : fInfo(info)
38 , fUniqueID(kNeedNewImageUniqueID == uniqueID ? SkNextID::ImageID() : uniqueID) {
39 SkASSERT(info.width() > 0);
40 SkASSERT(info.height() > 0);
41 }
42
peekPixels(SkPixmap * pm) const43 bool SkImage::peekPixels(SkPixmap* pm) const {
44 SkPixmap tmp;
45 if (!pm) {
46 pm = &tmp;
47 }
48 return as_IB(this)->onPeekPixels(pm);
49 }
50
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY,CachingHint chint) const51 bool SkImage::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX,
52 int srcY, CachingHint chint) const {
53 return as_IB(this)->onReadPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY, chint);
54 }
55
scalePixels(const SkPixmap & dst,SkFilterQuality quality,CachingHint chint) const56 bool SkImage::scalePixels(const SkPixmap& dst, SkFilterQuality quality, CachingHint chint) const {
57 if (this->width() == dst.width() && this->height() == dst.height()) {
58 return this->readPixels(dst, 0, 0, chint);
59 }
60
61 // Idea: If/when SkImageGenerator supports a native-scaling API (where the generator itself
62 // can scale more efficiently) we should take advantage of it here.
63 //
64 SkBitmap bm;
65 if (as_IB(this)->getROPixels(&bm, chint)) {
66 SkPixmap pmap;
67 // Note: By calling the pixmap scaler, we never cache the final result, so the chint
68 // is (currently) only being applied to the getROPixels. If we get a request to
69 // also attempt to cache the final (scaled) result, we would add that logic here.
70 //
71 return bm.peekPixels(&pmap) && pmap.scalePixels(dst, quality);
72 }
73 return false;
74 }
75
76 ///////////////////////////////////////////////////////////////////////////////////////////////////
77
colorType() const78 SkColorType SkImage::colorType() const { return fInfo.colorType(); }
79
alphaType() const80 SkAlphaType SkImage::alphaType() const { return fInfo.alphaType(); }
81
colorSpace() const82 SkColorSpace* SkImage::colorSpace() const { return fInfo.colorSpace(); }
83
refColorSpace() const84 sk_sp<SkColorSpace> SkImage::refColorSpace() const { return fInfo.refColorSpace(); }
85
makeShader(SkTileMode tmx,SkTileMode tmy,const SkMatrix * localMatrix) const86 sk_sp<SkShader> SkImage::makeShader(SkTileMode tmx, SkTileMode tmy,
87 const SkMatrix* localMatrix) const {
88 return SkImageShader::Make(sk_ref_sp(const_cast<SkImage*>(this)), tmx, tmy, localMatrix);
89 }
90
encodeToData(SkEncodedImageFormat type,int quality) const91 sk_sp<SkData> SkImage::encodeToData(SkEncodedImageFormat type, int quality) const {
92 SkBitmap bm;
93 if (as_IB(this)->getROPixels(&bm)) {
94 return SkEncodeBitmap(bm, type, quality);
95 }
96 return nullptr;
97 }
98
encodeToData() const99 sk_sp<SkData> SkImage::encodeToData() const {
100 if (auto encoded = this->refEncodedData()) {
101 return encoded;
102 }
103
104 return this->encodeToData(SkEncodedImageFormat::kPNG, 100);
105 }
106
refEncodedData() const107 sk_sp<SkData> SkImage::refEncodedData() const {
108 return sk_sp<SkData>(as_IB(this)->onRefEncoded());
109 }
110
MakeFromEncoded(sk_sp<SkData> encoded,const SkIRect * subset)111 sk_sp<SkImage> SkImage::MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset) {
112 if (nullptr == encoded || 0 == encoded->size()) {
113 return nullptr;
114 }
115 return SkImage::MakeFromGenerator(SkImageGenerator::MakeFromEncoded(std::move(encoded)),
116 subset);
117 }
118
119 ///////////////////////////////////////////////////////////////////////////////////////////////////
120
makeSubset(const SkIRect & subset) const121 sk_sp<SkImage> SkImage::makeSubset(const SkIRect& subset) const {
122 if (subset.isEmpty()) {
123 return nullptr;
124 }
125
126 const SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
127 if (!bounds.contains(subset)) {
128 return nullptr;
129 }
130
131 // optimization : return self if the subset == our bounds
132 if (bounds == subset) {
133 return sk_ref_sp(const_cast<SkImage*>(this));
134 }
135
136 // CONTEXT TODO: propagate the context parameter to the top-level API
137 #if SK_SUPPORT_GPU
138 return as_IB(this)->onMakeSubset(as_IB(this)->context(), subset);
139 #else
140 return as_IB(this)->onMakeSubset(nullptr, subset);
141 #endif
142 }
143
144 #if SK_SUPPORT_GPU
145
getTexture() const146 GrTexture* SkImage::getTexture() const {
147 return as_IB(this)->onGetTexture();
148 }
149
isTextureBacked() const150 bool SkImage::isTextureBacked() const { return as_IB(this)->onIsTextureBacked(); }
151
getBackendTexture(bool flushPendingGrContextIO,GrSurfaceOrigin * origin) const152 GrBackendTexture SkImage::getBackendTexture(bool flushPendingGrContextIO,
153 GrSurfaceOrigin* origin) const {
154 return as_IB(this)->onGetBackendTexture(flushPendingGrContextIO, origin);
155 }
156
isValid(GrContext * context) const157 bool SkImage::isValid(GrContext* context) const {
158 if (context && context->abandoned()) {
159 return false;
160 }
161 return as_IB(this)->onIsValid(context);
162 }
163
flush(GrContext * context,const GrFlushInfo & flushInfo)164 GrSemaphoresSubmitted SkImage::flush(GrContext* context, const GrFlushInfo& flushInfo) {
165 return as_IB(this)->onFlush(context, flushInfo);
166 }
167
flush(GrContext * context)168 void SkImage::flush(GrContext* context) { as_IB(this)->onFlush(context, {}); }
169
170 #else
171
getTexture() const172 GrTexture* SkImage::getTexture() const { return nullptr; }
173
isTextureBacked() const174 bool SkImage::isTextureBacked() const { return false; }
175
getBackendTexture(bool flushPendingGrContextIO,GrSurfaceOrigin * origin) const176 GrBackendTexture SkImage::getBackendTexture(bool flushPendingGrContextIO,
177 GrSurfaceOrigin* origin) const {
178 return GrBackendTexture(); // invalid
179 }
180
isValid(GrContext * context) const181 bool SkImage::isValid(GrContext* context) const {
182 if (context) {
183 return false;
184 }
185 return as_IB(this)->onIsValid(context);
186 }
187
flush(GrContext *,const GrFlushInfo &)188 GrSemaphoresSubmitted SkImage::flush(GrContext*, const GrFlushInfo&) {
189 return GrSemaphoresSubmitted::kNo;
190 }
191
flush(GrContext *)192 void SkImage::flush(GrContext*) {}
193
194 #endif
195
196 ///////////////////////////////////////////////////////////////////////////////
197
SkImage_Base(const SkImageInfo & info,uint32_t uniqueID)198 SkImage_Base::SkImage_Base(const SkImageInfo& info, uint32_t uniqueID)
199 : INHERITED(info, uniqueID), fAddedToRasterCache(false) {}
200
~SkImage_Base()201 SkImage_Base::~SkImage_Base() {
202 if (fAddedToRasterCache.load()) {
203 SkNotifyBitmapGenIDIsStale(this->uniqueID());
204 }
205 }
206
onGetBackendTexture(bool flushPendingGrContextIO,GrSurfaceOrigin * origin) const207 GrBackendTexture SkImage_Base::onGetBackendTexture(bool flushPendingGrContextIO,
208 GrSurfaceOrigin* origin) const {
209 return GrBackendTexture(); // invalid
210 }
211
readPixels(const SkPixmap & pmap,int srcX,int srcY,CachingHint chint) const212 bool SkImage::readPixels(const SkPixmap& pmap, int srcX, int srcY, CachingHint chint) const {
213 return this->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), srcX, srcY, chint);
214 }
215
216 ///////////////////////////////////////////////////////////////////////////////////////////////////
217
MakeFromBitmap(const SkBitmap & bm)218 sk_sp<SkImage> SkImage::MakeFromBitmap(const SkBitmap& bm) {
219 if (!bm.pixelRef()) {
220 return nullptr;
221 }
222
223 return SkMakeImageFromRasterBitmap(bm, kIfMutable_SkCopyPixelsMode);
224 }
225
asLegacyBitmap(SkBitmap * bitmap,LegacyBitmapMode) const226 bool SkImage::asLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode ) const {
227 return as_IB(this)->onAsLegacyBitmap(bitmap);
228 }
229
getPlanes(SkYUVASizeInfo *,SkYUVAIndex[4],SkYUVColorSpace *,const void * [4])230 sk_sp<SkCachedData> SkImage_Base::getPlanes(SkYUVASizeInfo*, SkYUVAIndex[4],
231 SkYUVColorSpace*, const void*[4]) {
232 return nullptr;
233 }
234
onAsLegacyBitmap(SkBitmap * bitmap) const235 bool SkImage_Base::onAsLegacyBitmap(SkBitmap* bitmap) const {
236 // As the base-class, all we can do is make a copy (regardless of mode).
237 // Subclasses that want to be more optimal should override.
238 SkImageInfo info = fInfo.makeColorType(kN32_SkColorType).makeColorSpace(nullptr);
239 if (!bitmap->tryAllocPixels(info)) {
240 return false;
241 }
242 if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
243 bitmap->reset();
244 return false;
245 }
246
247 bitmap->setImmutable();
248 return true;
249 }
250
MakeFromPicture(sk_sp<SkPicture> picture,const SkISize & dimensions,const SkMatrix * matrix,const SkPaint * paint,BitDepth bitDepth,sk_sp<SkColorSpace> colorSpace)251 sk_sp<SkImage> SkImage::MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
252 const SkMatrix* matrix, const SkPaint* paint,
253 BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) {
254 return MakeFromGenerator(SkImageGenerator::MakeFromPicture(dimensions, std::move(picture),
255 matrix, paint, bitDepth,
256 std::move(colorSpace)));
257 }
258
makeWithFilter(const SkImageFilter * filter,const SkIRect & subset,const SkIRect & clipBounds,SkIRect * outSubset,SkIPoint * offset) const259 sk_sp<SkImage> SkImage::makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,
260 const SkIRect& clipBounds, SkIRect* outSubset,
261 SkIPoint* offset) const {
262 GrContext* context = as_IB(this)->context();
263
264 return this->makeWithFilter(context, filter, subset, clipBounds, outSubset, offset);
265 }
266
makeWithFilter(GrContext * grContext,const SkImageFilter * filter,const SkIRect & subset,const SkIRect & clipBounds,SkIRect * outSubset,SkIPoint * offset) const267 sk_sp<SkImage> SkImage::makeWithFilter(GrContext* grContext,
268 const SkImageFilter* filter, const SkIRect& subset,
269 const SkIRect& clipBounds, SkIRect* outSubset,
270 SkIPoint* offset) const {
271 if (!filter || !outSubset || !offset || !this->bounds().contains(subset)) {
272 return nullptr;
273 }
274 sk_sp<SkSpecialImage> srcSpecialImage =
275 #if SK_SUPPORT_GPU
276 SkSpecialImage::MakeFromImage(grContext, subset, sk_ref_sp(const_cast<SkImage*>(this)));
277 #else
278 SkSpecialImage::MakeFromImage(nullptr, subset, sk_ref_sp(const_cast<SkImage*>(this)));
279 #endif
280 if (!srcSpecialImage) {
281 return nullptr;
282 }
283
284 sk_sp<SkImageFilterCache> cache(
285 SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize));
286
287 // The filters operate in the local space of the src image, where (0,0) corresponds to the
288 // subset's top left corner. But the clip bounds and any crop rects on the filters are in the
289 // original coordinate system, so configure the CTM to correct crop rects and explicitly adjust
290 // the clip bounds (since it is assumed to already be in image space).
291 SkImageFilter_Base::Context context(SkMatrix::MakeTrans(-subset.x(), -subset.y()),
292 clipBounds.makeOffset(-subset.topLeft()),
293 cache.get(), fInfo.colorType(), fInfo.colorSpace(),
294 srcSpecialImage.get());
295
296 sk_sp<SkSpecialImage> result = as_IFB(filter)->filterImage(context).imageAndOffset(offset);
297 if (!result) {
298 return nullptr;
299 }
300
301 // The output image and offset are relative to the subset rectangle, so the offset needs to
302 // be shifted to put it in the correct spot with respect to the original coordinate system
303 offset->fX += subset.x();
304 offset->fY += subset.y();
305
306 // Final clip against the exact clipBounds (the clip provided in the context gets adjusted
307 // to account for pixel-moving filters so doesn't always exactly match when finished). The
308 // clipBounds are translated into the clippedDstRect coordinate space, including the
309 // result->subset() ensures that the result's image pixel origin does not affect results.
310 SkIRect dstRect = result->subset();
311 SkIRect clippedDstRect = dstRect;
312 if (!clippedDstRect.intersect(clipBounds.makeOffset(result->subset().topLeft() - *offset))) {
313 return nullptr;
314 }
315
316 // Adjust the geometric offset if the top-left corner moved as well
317 offset->fX += (clippedDstRect.x() - dstRect.x());
318 offset->fY += (clippedDstRect.y() - dstRect.y());
319 *outSubset = clippedDstRect;
320 return result->asImage();
321 }
322
isLazyGenerated() const323 bool SkImage::isLazyGenerated() const {
324 return as_IB(this)->onIsLazyGenerated();
325 }
326
isAlphaOnly() const327 bool SkImage::isAlphaOnly() const { return SkColorTypeIsAlphaOnly(fInfo.colorType()); }
328
makeColorSpace(sk_sp<SkColorSpace> target) const329 sk_sp<SkImage> SkImage::makeColorSpace(sk_sp<SkColorSpace> target) const {
330 if (!target) {
331 return nullptr;
332 }
333
334 // No need to create a new image if:
335 // (1) The color spaces are equal.
336 // (2) The color type is kAlpha8.
337 SkColorSpace* colorSpace = this->colorSpace();
338 if (!colorSpace) {
339 colorSpace = sk_srgb_singleton();
340 }
341 if (SkColorSpace::Equals(colorSpace, target.get()) || this->isAlphaOnly()) {
342 return sk_ref_sp(const_cast<SkImage*>(this));
343 }
344
345 // CONTEXT TODO: propagate the context parameter to the top-level API
346 #if SK_SUPPORT_GPU
347 return as_IB(this)->onMakeColorTypeAndColorSpace(as_IB(this)->context(),
348 #else
349 return as_IB(this)->onMakeColorTypeAndColorSpace(nullptr,
350 #endif
351 this->colorType(), std::move(target));
352 }
353
makeColorTypeAndColorSpace(SkColorType targetColorType,sk_sp<SkColorSpace> targetColorSpace) const354 sk_sp<SkImage> SkImage::makeColorTypeAndColorSpace(SkColorType targetColorType,
355 sk_sp<SkColorSpace> targetColorSpace) const {
356 if (kUnknown_SkColorType == targetColorType || !targetColorSpace) {
357 return nullptr;
358 }
359
360 SkColorType colorType = this->colorType();
361 SkColorSpace* colorSpace = this->colorSpace();
362 if (!colorSpace) {
363 colorSpace = sk_srgb_singleton();
364 }
365 if (colorType == targetColorType &&
366 (SkColorSpace::Equals(colorSpace, targetColorSpace.get()) || this->isAlphaOnly())) {
367 return sk_ref_sp(const_cast<SkImage*>(this));
368 }
369
370 // CONTEXT TODO: propagate the context parameter to the top-level API
371 #if SK_SUPPORT_GPU
372 return as_IB(this)->onMakeColorTypeAndColorSpace(as_IB(this)->context(),
373 #else
374 return as_IB(this)->onMakeColorTypeAndColorSpace(nullptr,
375 #endif
376 targetColorType, std::move(targetColorSpace));
377 }
378
reinterpretColorSpace(sk_sp<SkColorSpace> target) const379 sk_sp<SkImage> SkImage::reinterpretColorSpace(sk_sp<SkColorSpace> target) const {
380 if (!target) {
381 return nullptr;
382 }
383
384 // No need to create a new image if:
385 // (1) The color spaces are equal.
386 // (2) The color type is kAlpha8.
387 SkColorSpace* colorSpace = this->colorSpace();
388 if (!colorSpace) {
389 colorSpace = sk_srgb_singleton();
390 }
391 if (SkColorSpace::Equals(colorSpace, target.get()) || this->isAlphaOnly()) {
392 return sk_ref_sp(const_cast<SkImage*>(this));
393 }
394
395 return as_IB(this)->onReinterpretColorSpace(std::move(target));
396 }
397
makeNonTextureImage() const398 sk_sp<SkImage> SkImage::makeNonTextureImage() const {
399 if (!this->isTextureBacked()) {
400 return sk_ref_sp(const_cast<SkImage*>(this));
401 }
402 return this->makeRasterImage();
403 }
404
makeRasterImage(CachingHint chint) const405 sk_sp<SkImage> SkImage::makeRasterImage(CachingHint chint) const {
406 SkPixmap pm;
407 if (this->peekPixels(&pm)) {
408 return sk_ref_sp(const_cast<SkImage*>(this));
409 }
410
411 const size_t rowBytes = fInfo.minRowBytes();
412 size_t size = fInfo.computeByteSize(rowBytes);
413 if (SkImageInfo::ByteSizeOverflowed(size)) {
414 return nullptr;
415 }
416
417 sk_sp<SkData> data = SkData::MakeUninitialized(size);
418 pm = {fInfo.makeColorSpace(nullptr), data->writable_data(), fInfo.minRowBytes()};
419 if (!this->readPixels(pm, 0, 0, chint)) {
420 return nullptr;
421 }
422
423 return SkImage::MakeRasterData(fInfo, std::move(data), rowBytes);
424 }
425
426 //////////////////////////////////////////////////////////////////////////////////////
427
428 #if !SK_SUPPORT_GPU
429
DecodeToTexture(GrContext *,const void *,size_t,const SkIRect *)430 sk_sp<SkImage> SkImage::DecodeToTexture(GrContext*, const void*, size_t, const SkIRect*) {
431 return nullptr;
432 }
433
MakeFromTexture(GrContext * ctx,const GrBackendTexture & tex,GrSurfaceOrigin origin,SkColorType ct,SkAlphaType at,sk_sp<SkColorSpace> cs,TextureReleaseProc releaseP,ReleaseContext releaseC)434 sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
435 const GrBackendTexture& tex, GrSurfaceOrigin origin,
436 SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
437 TextureReleaseProc releaseP, ReleaseContext releaseC) {
438 return nullptr;
439 }
440
MakeFromCompressedTexture(GrContext * ctx,const GrBackendTexture & tex,GrSurfaceOrigin origin,SkAlphaType at,sk_sp<SkColorSpace> cs,TextureReleaseProc releaseP,ReleaseContext releaseC)441 sk_sp<SkImage> SkImage::MakeFromCompressedTexture(GrContext* ctx,
442 const GrBackendTexture& tex,
443 GrSurfaceOrigin origin,
444 SkAlphaType at,
445 sk_sp<SkColorSpace> cs,
446 TextureReleaseProc releaseP,
447 ReleaseContext releaseC) {
448 return nullptr;
449 }
450
MakeBackendTextureFromSkImage(GrContext *,sk_sp<SkImage>,GrBackendTexture *,BackendTextureReleaseProc *)451 bool SkImage::MakeBackendTextureFromSkImage(GrContext*,
452 sk_sp<SkImage>,
453 GrBackendTexture*,
454 BackendTextureReleaseProc*) {
455 return false;
456 }
457
MakeFromAdoptedTexture(GrContext * ctx,const GrBackendTexture & tex,GrSurfaceOrigin origin,SkColorType ct,SkAlphaType at,sk_sp<SkColorSpace> cs)458 sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
459 const GrBackendTexture& tex, GrSurfaceOrigin origin,
460 SkColorType ct, SkAlphaType at,
461 sk_sp<SkColorSpace> cs) {
462 return nullptr;
463 }
464
MakeFromYUVATexturesCopy(GrContext * context,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize imageSize,GrSurfaceOrigin imageOrigin,sk_sp<SkColorSpace> imageColorSpace)465 sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* context,
466 SkYUVColorSpace yuvColorSpace,
467 const GrBackendTexture yuvaTextures[],
468 const SkYUVAIndex yuvaIndices[4],
469 SkISize imageSize,
470 GrSurfaceOrigin imageOrigin,
471 sk_sp<SkColorSpace> imageColorSpace) {
472 return nullptr;
473 }
474
MakeFromYUVATexturesCopyWithExternalBackend(GrContext * context,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvaTextures[],const SkYUVAIndex yuvaIndices[4],SkISize imageSize,GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace,TextureReleaseProc textureReleaseProc,ReleaseContext releaseContext)475 sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
476 GrContext* context,
477 SkYUVColorSpace yuvColorSpace,
478 const GrBackendTexture yuvaTextures[],
479 const SkYUVAIndex yuvaIndices[4],
480 SkISize imageSize,
481 GrSurfaceOrigin imageOrigin,
482 const GrBackendTexture& backendTexture,
483 sk_sp<SkColorSpace> imageColorSpace,
484 TextureReleaseProc textureReleaseProc,
485 ReleaseContext releaseContext) {
486 return nullptr;
487 }
488
MakeFromYUVTexturesCopy(GrContext * ctx,SkYUVColorSpace space,const GrBackendTexture[3],GrSurfaceOrigin origin,sk_sp<SkColorSpace> imageColorSpace)489 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace space,
490 const GrBackendTexture[3],
491 GrSurfaceOrigin origin,
492 sk_sp<SkColorSpace> imageColorSpace) {
493 return nullptr;
494 }
495
MakeFromYUVTexturesCopyWithExternalBackend(GrContext * context,SkYUVColorSpace yuvColorSpace,const GrBackendTexture yuvTextures[3],GrSurfaceOrigin surfaceOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> colorSpace)496 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
497 GrContext* context, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
498 GrSurfaceOrigin surfaceOrigin, const GrBackendTexture& backendTexture,
499 sk_sp<SkColorSpace> colorSpace) {
500 return nullptr;
501 }
502
MakeFromNV12TexturesCopy(GrContext * ctx,SkYUVColorSpace space,const GrBackendTexture[2],GrSurfaceOrigin origin,sk_sp<SkColorSpace> imageColorSpace)503 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace space,
504 const GrBackendTexture[2],
505 GrSurfaceOrigin origin,
506 sk_sp<SkColorSpace> imageColorSpace) {
507 return nullptr;
508 }
509
makeTextureImage(GrContext *,GrMipMapped mipMapped) const510 sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, GrMipMapped mipMapped) const {
511 return nullptr;
512 }
513
MakeFromNV12TexturesCopyWithExternalBackend(GrContext * context,SkYUVColorSpace yuvColorSpace,const GrBackendTexture nv12Textures[2],GrSurfaceOrigin imageOrigin,const GrBackendTexture & backendTexture,sk_sp<SkColorSpace> imageColorSpace,TextureReleaseProc textureReleaseProc,ReleaseContext releaseContext)514 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
515 GrContext* context,
516 SkYUVColorSpace yuvColorSpace,
517 const GrBackendTexture nv12Textures[2],
518 GrSurfaceOrigin imageOrigin,
519 const GrBackendTexture& backendTexture,
520 sk_sp<SkColorSpace> imageColorSpace,
521 TextureReleaseProc textureReleaseProc,
522 ReleaseContext releaseContext) {
523 return nullptr;
524 }
525
526 #endif
527
528 ///////////////////////////////////////////////////////////////////////////////////////////////////
529
SkImage_pinAsTexture(const SkImage * image,GrContext * ctx)530 bool SkImage_pinAsTexture(const SkImage* image, GrContext* ctx) {
531 SkASSERT(image);
532 SkASSERT(ctx);
533 return as_IB(image)->onPinAsTexture(ctx);
534 }
535
SkImage_unpinAsTexture(const SkImage * image,GrContext * ctx)536 void SkImage_unpinAsTexture(const SkImage* image, GrContext* ctx) {
537 SkASSERT(image);
538 SkASSERT(ctx);
539 as_IB(image)->onUnpinAsTexture(ctx);
540 }
541
SkImage_getSubset(const SkImage * image)542 SkIRect SkImage_getSubset(const SkImage* image) {
543 SkASSERT(image);
544 return as_IB(image)->onGetSubset();
545 }
546