SkImage_Gpu.cpp revision 2d5b7147032e3806b5895667a899440119707c2d
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 "SkAutoPixmapStorage.h" 9#include "GrCaps.h" 10#include "GrContext.h" 11#include "GrDrawContext.h" 12#include "GrImageIDTextureAdjuster.h" 13#include "effects/GrYUVEffect.h" 14#include "SkCanvas.h" 15#include "SkBitmapCache.h" 16#include "SkGrPriv.h" 17#include "SkImage_Gpu.h" 18#include "SkMipMap.h" 19#include "SkPixelRef.h" 20 21SkImage_Gpu::SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType at, GrTexture* tex, 22 sk_sp<SkColorSpace> colorSpace, SkBudgeted budgeted) 23 : INHERITED(w, h, uniqueID) 24 , fTexture(SkRef(tex)) 25 , fAlphaType(at) 26 , fBudgeted(budgeted) 27 , fColorSpace(std::move(colorSpace)) 28 , fAddedRasterVersionToCache(false) 29{ 30 SkASSERT(tex->width() == w); 31 SkASSERT(tex->height() == h); 32} 33 34SkImage_Gpu::~SkImage_Gpu() { 35 if (fAddedRasterVersionToCache.load()) { 36 SkNotifyBitmapGenIDIsStale(this->uniqueID()); 37 } 38} 39 40extern void SkTextureImageApplyBudgetedDecision(SkImage* image) { 41 if (image->isTextureBacked()) { 42 ((SkImage_Gpu*)image)->applyBudgetDecision(); 43 } 44} 45 46SkImageInfo SkImage_Gpu::onImageInfo() const { 47 SkColorType ct; 48 if (!GrPixelConfigToColorType(fTexture->config(), &ct)) { 49 ct = kUnknown_SkColorType; 50 } 51 return SkImageInfo::Make(fTexture->width(), fTexture->height(), ct, fAlphaType, fColorSpace); 52} 53 54static SkImageInfo make_info(int w, int h, bool isOpaque, sk_sp<SkColorSpace> colorSpace) { 55 return SkImageInfo::MakeN32(w, h, isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType, 56 std::move(colorSpace)); 57} 58 59bool SkImage_Gpu::getROPixels(SkBitmap* dst, CachingHint chint) const { 60 if (SkBitmapCache::Find(this->uniqueID(), dst)) { 61 SkASSERT(dst->getGenerationID() == this->uniqueID()); 62 SkASSERT(dst->isImmutable()); 63 SkASSERT(dst->getPixels()); 64 return true; 65 } 66 67 if (!dst->tryAllocPixels(make_info(this->width(), this->height(), this->isOpaque(), 68 this->fColorSpace))) { 69 return false; 70 } 71 if (!fTexture->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig, 72 dst->getPixels(), dst->rowBytes())) { 73 return false; 74 } 75 76 dst->pixelRef()->setImmutableWithID(this->uniqueID()); 77 if (kAllow_CachingHint == chint) { 78 SkBitmapCache::Add(this->uniqueID(), *dst); 79 fAddedRasterVersionToCache.store(true); 80 } 81 return true; 82} 83 84GrTexture* SkImage_Gpu::asTextureRef(GrContext* ctx, const GrTextureParams& params, 85 SkSourceGammaTreatment gammaTreatment) const { 86 GrTextureAdjuster adjuster(this->peekTexture(), this->bounds(), this->uniqueID(), 87 this->onImageInfo().colorSpace()); 88 return adjuster.refTextureSafeForParams(params, gammaTreatment, nullptr); 89} 90 91bool SkImage_Gpu::isOpaque() const { 92 return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType; 93} 94 95static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) { 96 switch (info.colorType()) { 97 case kRGBA_8888_SkColorType: 98 case kBGRA_8888_SkColorType: 99 break; 100 default: 101 return; // nothing to do 102 } 103 104 // SkColor is not necesarily RGBA or BGRA, but it is one of them on little-endian, 105 // and in either case, the alpha-byte is always in the same place, so we can safely call 106 // SkPreMultiplyColor() 107 // 108 SkColor* row = (SkColor*)pixels; 109 for (int y = 0; y < info.height(); ++y) { 110 for (int x = 0; x < info.width(); ++x) { 111 row[x] = SkPreMultiplyColor(row[x]); 112 } 113 } 114} 115 116bool SkImage_Gpu::onReadPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 117 int srcX, int srcY, CachingHint) const { 118 GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fTexture->getContext()->caps()); 119 uint32_t flags = 0; 120 if (kUnpremul_SkAlphaType == info.alphaType() && kPremul_SkAlphaType == fAlphaType) { 121 // let the GPU perform this transformation for us 122 flags = GrContext::kUnpremul_PixelOpsFlag; 123 } 124 if (!fTexture->readPixels(srcX, srcY, info.width(), info.height(), config, 125 pixels, rowBytes, flags)) { 126 return false; 127 } 128 // do we have to manually fix-up the alpha channel? 129 // src dst 130 // unpremul premul fix manually 131 // premul unpremul done by kUnpremul_PixelOpsFlag 132 // all other combos need to change. 133 // 134 // Should this be handled by Ganesh? todo:? 135 // 136 if (kPremul_SkAlphaType == info.alphaType() && kUnpremul_SkAlphaType == fAlphaType) { 137 apply_premul(info, pixels, rowBytes); 138 } 139 return true; 140} 141 142sk_sp<SkImage> SkImage_Gpu::onMakeSubset(const SkIRect& subset) const { 143 GrContext* ctx = fTexture->getContext(); 144 GrSurfaceDesc desc = fTexture->desc(); 145 desc.fWidth = subset.width(); 146 desc.fHeight = subset.height(); 147 148 sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, fBudgeted)); 149 if (!subTx) { 150 return nullptr; 151 } 152 ctx->copySurface(subTx.get(), fTexture, subset, SkIPoint::Make(0, 0)); 153 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID, 154 fAlphaType, subTx.get(), fColorSpace, fBudgeted); 155} 156 157/////////////////////////////////////////////////////////////////////////////////////////////////// 158 159static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx, const GrBackendTextureDesc& desc, 160 SkAlphaType at, sk_sp<SkColorSpace> colorSpace, 161 GrWrapOwnership ownership, 162 SkImage::TextureReleaseProc releaseProc, 163 SkImage::ReleaseContext releaseCtx) { 164 if (desc.fWidth <= 0 || desc.fHeight <= 0) { 165 return nullptr; 166 } 167 SkAutoTUnref<GrTexture> tex(ctx->textureProvider()->wrapBackendTexture(desc, ownership)); 168 if (!tex) { 169 return nullptr; 170 } 171 if (releaseProc) { 172 tex->setRelease(releaseProc, releaseCtx); 173 } 174 175 const SkBudgeted budgeted = SkBudgeted::kNo; 176 return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID, 177 at, tex, colorSpace, budgeted); 178} 179 180sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc, 181 SkAlphaType at, sk_sp<SkColorSpace> cs, 182 TextureReleaseProc releaseP, ReleaseContext releaseC) { 183 return new_wrapped_texture_common(ctx, desc, at, std::move(cs), kBorrow_GrWrapOwnership, 184 releaseP, releaseC); 185} 186 187sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx, const GrBackendTextureDesc& desc, 188 SkAlphaType at, sk_sp<SkColorSpace> cs) { 189 return new_wrapped_texture_common(ctx, desc, at, std::move(cs), kAdopt_GrWrapOwnership, 190 nullptr, nullptr); 191} 192 193static sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpace colorSpace, 194 bool nv12, 195 const GrBackendObject yuvTextureHandles[], 196 const SkISize yuvSizes[], 197 GrSurfaceOrigin origin, 198 sk_sp<SkColorSpace> imageColorSpace) { 199 const SkBudgeted budgeted = SkBudgeted::kYes; 200 201 if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 || yuvSizes[1].fWidth <= 0 || 202 yuvSizes[1].fHeight <= 0) { 203 return nullptr; 204 } 205 if (!nv12 && (yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0)) { 206 return nullptr; 207 } 208 209 const GrPixelConfig kConfig = nv12 ? kRGBA_8888_GrPixelConfig : kAlpha_8_GrPixelConfig; 210 211 GrBackendTextureDesc yDesc; 212 yDesc.fConfig = kConfig; 213 yDesc.fOrigin = origin; 214 yDesc.fSampleCnt = 0; 215 yDesc.fTextureHandle = yuvTextureHandles[0]; 216 yDesc.fWidth = yuvSizes[0].fWidth; 217 yDesc.fHeight = yuvSizes[0].fHeight; 218 219 GrBackendTextureDesc uDesc; 220 uDesc.fConfig = kConfig; 221 uDesc.fOrigin = origin; 222 uDesc.fSampleCnt = 0; 223 uDesc.fTextureHandle = yuvTextureHandles[1]; 224 uDesc.fWidth = yuvSizes[1].fWidth; 225 uDesc.fHeight = yuvSizes[1].fHeight; 226 227 sk_sp<GrTexture> yTex( 228 ctx->textureProvider()->wrapBackendTexture(yDesc, kBorrow_GrWrapOwnership)); 229 sk_sp<GrTexture> uTex( 230 ctx->textureProvider()->wrapBackendTexture(uDesc, kBorrow_GrWrapOwnership)); 231 sk_sp<GrTexture> vTex; 232 if (nv12) { 233 vTex = uTex; 234 } else { 235 GrBackendTextureDesc vDesc; 236 vDesc.fConfig = kConfig; 237 vDesc.fOrigin = origin; 238 vDesc.fSampleCnt = 0; 239 vDesc.fTextureHandle = yuvTextureHandles[2]; 240 vDesc.fWidth = yuvSizes[2].fWidth; 241 vDesc.fHeight = yuvSizes[2].fHeight; 242 243 vTex = sk_sp<GrTexture>( 244 ctx->textureProvider()->wrapBackendTexture(vDesc, kBorrow_GrWrapOwnership)); 245 } 246 if (!yTex || !uTex || !vTex) { 247 return nullptr; 248 } 249 250 const int width = yuvSizes[0].fWidth; 251 const int height = yuvSizes[0].fHeight; 252 253 // Needs to be a render target in order to draw to it for the yuv->rgb conversion. 254 sk_sp<GrDrawContext> drawContext(ctx->makeDrawContext(SkBackingFit::kExact, 255 width, height, 256 kRGBA_8888_GrPixelConfig, 257 std::move(imageColorSpace), 258 0, 259 origin)); 260 if (!drawContext) { 261 return nullptr; 262 } 263 264 GrPaint paint; 265 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); 266 paint.addColorFragmentProcessor( 267 GrYUVEffect::MakeYUVToRGB(yTex.get(), uTex.get(), vTex.get(), yuvSizes, colorSpace, nv12)); 268 269 const SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 270 271 drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect); 272 ctx->flushSurfaceWrites(drawContext->accessRenderTarget()); 273 return sk_make_sp<SkImage_Gpu>(width, height, kNeedNewImageUniqueID, 274 kOpaque_SkAlphaType, drawContext->asTexture().get(), 275 sk_ref_sp(drawContext->getColorSpace()), budgeted); 276} 277 278sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, 279 const GrBackendObject yuvTextureHandles[3], 280 const SkISize yuvSizes[3], GrSurfaceOrigin origin, 281 sk_sp<SkColorSpace> imageColorSpace) { 282 return make_from_yuv_textures_copy(ctx, colorSpace, false, yuvTextureHandles, yuvSizes, origin, 283 std::move(imageColorSpace)); 284} 285 286sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, 287 const GrBackendObject yuvTextureHandles[2], 288 const SkISize yuvSizes[2], 289 GrSurfaceOrigin origin, 290 sk_sp<SkColorSpace> imageColorSpace) { 291 return make_from_yuv_textures_copy(ctx, colorSpace, true, yuvTextureHandles, yuvSizes, origin, 292 std::move(imageColorSpace)); 293} 294 295static sk_sp<SkImage> create_image_from_maker(GrTextureMaker* maker, SkAlphaType at, uint32_t id) { 296 SkAutoTUnref<GrTexture> texture(maker->refTextureForParams(GrTextureParams::ClampNoFilter(), 297 SkSourceGammaTreatment::kRespect)); 298 if (!texture) { 299 return nullptr; 300 } 301 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), id, at, texture, 302 sk_ref_sp(maker->getColorSpace()), SkBudgeted::kNo); 303} 304 305sk_sp<SkImage> SkImage::makeTextureImage(GrContext *context) const { 306 if (!context) { 307 return nullptr; 308 } 309 if (GrTexture* peek = as_IB(this)->peekTexture()) { 310 return peek->getContext() == context ? sk_ref_sp(const_cast<SkImage*>(this)) : nullptr; 311 } 312 // No way to check whether a image is premul or not? 313 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 314 315 if (SkImageCacherator* cacher = as_IB(this)->peekCacherator()) { 316 GrImageTextureMaker maker(context, cacher, this, kDisallow_CachingHint); 317 return create_image_from_maker(&maker, at, this->uniqueID()); 318 } 319 320 if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) { 321 GrBitmapTextureMaker maker(context, *bmp); 322 return create_image_from_maker(&maker, at, this->uniqueID()); 323 } 324 return nullptr; 325} 326 327sk_sp<SkImage> SkImage::makeNonTextureImage() const { 328 if (!this->isTextureBacked()) { 329 return sk_ref_sp(const_cast<SkImage*>(this)); 330 } 331 SkImageInfo info = as_IB(this)->onImageInfo(); 332 size_t rowBytes = info.minRowBytes(); 333 size_t size = info.getSafeSize(rowBytes); 334 auto data = SkData::MakeUninitialized(size); 335 if (!data) { 336 return nullptr; 337 } 338 SkPixmap pm(info, data->writable_data(), rowBytes); 339 if (!this->readPixels(pm, 0, 0, kDisallow_CachingHint)) { 340 return nullptr; 341 } 342 return MakeRasterData(info, data, rowBytes); 343} 344 345sk_sp<SkImage> SkImage::MakeTextureFromPixmap(GrContext* ctx, const SkPixmap& pixmap, 346 SkBudgeted budgeted) { 347 if (!ctx) { 348 return nullptr; 349 } 350 SkAutoTUnref<GrTexture> texture(GrUploadPixmapToTexture(ctx, pixmap, budgeted)); 351 if (!texture) { 352 return nullptr; 353 } 354 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID, 355 pixmap.alphaType(), texture, 356 sk_ref_sp(pixmap.info().colorSpace()), budgeted); 357} 358 359/////////////////////////////////////////////////////////////////////////////////////////////////// 360 361namespace { 362struct MipMapLevelData { 363 void* fPixelData; 364 size_t fRowBytes; 365}; 366 367struct DeferredTextureImage { 368 uint32_t fContextUniqueID; 369 // We don't store a SkImageInfo because it contains a ref-counted SkColorSpace. 370 int fWidth; 371 int fHeight; 372 SkColorType fColorType; 373 SkAlphaType fAlphaType; 374 void* fColorSpace; 375 size_t fColorSpaceSize; 376 int fColorTableCnt; 377 uint32_t* fColorTableData; 378 int fMipMapLevelCount; 379 // The fMipMapLevelData array may contain more than 1 element. 380 // It contains fMipMapLevelCount elements. 381 // That means this struct's size is not known at compile-time. 382 MipMapLevelData fMipMapLevelData[1]; 383}; 384} // anonymous namespace 385 386size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy, 387 const DeferredTextureImageUsageParams params[], 388 int paramCnt, void* buffer) const { 389 // Extract relevant min/max values from the params array. 390 int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel; 391 SkFilterQuality highestFilterQuality = params[0].fQuality; 392 for (int i = 1; i < paramCnt; ++i) { 393 if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel) 394 lowestPreScaleMipLevel = params[i].fPreScaleMipLevel; 395 if (highestFilterQuality < params[i].fQuality) 396 highestFilterQuality = params[i].fQuality; 397 } 398 399 const bool fillMode = SkToBool(buffer); 400 if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) { 401 return 0; 402 } 403 404 // Calculate scaling parameters. 405 bool isScaled = lowestPreScaleMipLevel != 0; 406 407 SkISize scaledSize; 408 if (isScaled) { 409 // SkMipMap::ComputeLevelSize takes an index into an SkMipMap. SkMipMaps don't contain the 410 // base level, so to get an SkMipMap index we must subtract one from the GL MipMap level. 411 scaledSize = SkMipMap::ComputeLevelSize(this->width(), this->height(), 412 lowestPreScaleMipLevel - 1); 413 } else { 414 scaledSize = SkISize::Make(this->width(), this->height()); 415 } 416 417 // We never want to scale at higher than SW medium quality, as SW medium matches GPU high. 418 SkFilterQuality scaleFilterQuality = highestFilterQuality; 419 if (scaleFilterQuality > kMedium_SkFilterQuality) { 420 scaleFilterQuality = kMedium_SkFilterQuality; 421 } 422 423 const int maxTextureSize = proxy.fCaps->maxTextureSize(); 424 if (scaledSize.width() > maxTextureSize || scaledSize.height() > maxTextureSize) { 425 return 0; 426 } 427 428 SkAutoPixmapStorage pixmap; 429 SkImageInfo info; 430 size_t pixelSize = 0; 431 size_t ctSize = 0; 432 int ctCount = 0; 433 if (!isScaled && this->peekPixels(&pixmap)) { 434 info = pixmap.info(); 435 pixelSize = SkAlign8(pixmap.getSafeSize()); 436 if (pixmap.ctable()) { 437 ctCount = pixmap.ctable()->count(); 438 ctSize = SkAlign8(pixmap.ctable()->count() * 4); 439 } 440 } else { 441 // Here we're just using presence of data to know whether there is a codec behind the image. 442 // In the future we will access the cacherator and get the exact data that we want to (e.g. 443 // yuv planes) upload. 444 sk_sp<SkData> data(this->refEncoded()); 445 if (!data && !this->peekPixels(nullptr)) { 446 return 0; 447 } 448 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 449 info = SkImageInfo::MakeN32(scaledSize.width(), scaledSize.height(), at); 450 pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr)); 451 if (fillMode) { 452 pixmap.alloc(info); 453 if (isScaled) { 454 if (!this->scalePixels(pixmap, scaleFilterQuality, 455 SkImage::kDisallow_CachingHint)) { 456 return 0; 457 } 458 } else { 459 if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHint)) { 460 return 0; 461 } 462 } 463 SkASSERT(!pixmap.ctable()); 464 } 465 } 466 int mipMapLevelCount = 1; 467 size_t size = 0; 468 size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage)); 469 size += dtiSize; 470 size += mipMapLevelCount * sizeof(MipMapLevelData); 471 size_t pixelOffset = size; 472 size += pixelSize; 473 size_t ctOffset = size; 474 size += ctSize; 475 size_t colorSpaceOffset = 0; 476 size_t colorSpaceSize = 0; 477 if (info.colorSpace()) { 478 colorSpaceOffset = size; 479 colorSpaceSize = info.colorSpace()->writeToMemory(nullptr); 480 size += colorSpaceSize; 481 } 482 if (!fillMode) { 483 return size; 484 } 485 intptr_t bufferAsInt = reinterpret_cast<intptr_t>(buffer); 486 void* pixels = reinterpret_cast<void*>(bufferAsInt + pixelOffset); 487 SkPMColor* ct = nullptr; 488 if (ctSize) { 489 ct = reinterpret_cast<SkPMColor*>(bufferAsInt + ctOffset); 490 } 491 492 memcpy(pixels, pixmap.addr(), pixmap.getSafeSize()); 493 if (ctSize) { 494 memcpy(ct, pixmap.ctable()->readColors(), ctSize); 495 } 496 497 SkASSERT(info == pixmap.info()); 498 size_t rowBytes = pixmap.rowBytes(); 499 DeferredTextureImage* dti = new (buffer) DeferredTextureImage(); 500 dti->fContextUniqueID = proxy.fContextUniqueID; 501 dti->fWidth = info.width(); 502 dti->fHeight = info.height(); 503 dti->fColorType = info.colorType(); 504 dti->fAlphaType = info.alphaType(); 505 dti->fColorTableCnt = ctCount; 506 dti->fColorTableData = ct; 507 dti->fMipMapLevelCount = mipMapLevelCount; 508 dti->fMipMapLevelData[0].fPixelData = pixels; 509 dti->fMipMapLevelData[0].fRowBytes = rowBytes; 510 if (colorSpaceSize) { 511 dti->fColorSpace = reinterpret_cast<void*>(bufferAsInt + colorSpaceOffset); 512 dti->fColorSpaceSize = colorSpaceSize; 513 info.colorSpace()->writeToMemory(dti->fColorSpace); 514 } else { 515 dti->fColorSpace = nullptr; 516 dti->fColorSpaceSize = 0; 517 } 518 return size; 519} 520 521sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, const void* data, 522 SkBudgeted budgeted) { 523 if (!data) { 524 return nullptr; 525 } 526 const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImage*>(data); 527 528 if (!context || context->uniqueID() != dti->fContextUniqueID) { 529 return nullptr; 530 } 531 SkAutoTUnref<SkColorTable> colorTable; 532 if (dti->fColorTableCnt) { 533 SkASSERT(dti->fColorTableData); 534 colorTable.reset(new SkColorTable(dti->fColorTableData, dti->fColorTableCnt)); 535 } 536 SkASSERT(dti->fMipMapLevelCount == 1); 537 sk_sp<SkColorSpace> colorSpace; 538 if (dti->fColorSpaceSize) { 539 colorSpace = SkColorSpace::Deserialize(dti->fColorSpace, dti->fColorSpaceSize); 540 } 541 SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight, 542 dti->fColorType, dti->fAlphaType, colorSpace); 543 SkPixmap pixmap; 544 pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData, 545 dti->fMipMapLevelData[0].fRowBytes, colorTable.get()); 546 return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted); 547} 548 549/////////////////////////////////////////////////////////////////////////////////////////////////// 550 551GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) { 552 GrContext* ctx = src->getContext(); 553 554 GrSurfaceDesc desc = src->desc(); 555 GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, nullptr, 0); 556 if (!dst) { 557 return nullptr; 558 } 559 560 const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight); 561 const SkIPoint dstP = SkIPoint::Make(0, 0); 562 ctx->copySurface(dst, src, srcR, dstP); 563 ctx->flushSurfaceWrites(dst); 564 return dst; 565} 566 567sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info, 568 const GrMipLevel* texels, int mipLevelCount, 569 SkBudgeted budgeted) { 570 if (!ctx) { 571 return nullptr; 572 } 573 SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, mipLevelCount)); 574 if (!texture) { 575 return nullptr; 576 } 577 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID, 578 info.alphaType(), texture, sk_ref_sp(info.colorSpace()), 579 budgeted); 580} 581