Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: src/image/SkImage_Gpu.cpp

Issue 2115023002: Store mipmap levels in deferred texture image (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Did I leak a SkBitmap? Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 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 "SkAutoPixmapStorage.h" 8 #include "SkAutoPixmapStorage.h"
9 #include "GrCaps.h" 9 #include "GrCaps.h"
10 #include "GrContext.h" 10 #include "GrContext.h"
11 #include "GrDrawContext.h" 11 #include "GrDrawContext.h"
12 #include "GrImageIDTextureAdjuster.h" 12 #include "GrImageIDTextureAdjuster.h"
13 #include "GrTexturePriv.h"
13 #include "effects/GrYUVEffect.h" 14 #include "effects/GrYUVEffect.h"
14 #include "SkCanvas.h" 15 #include "SkCanvas.h"
15 #include "SkBitmapCache.h" 16 #include "SkBitmapCache.h"
16 #include "SkGrPriv.h" 17 #include "SkGrPriv.h"
17 #include "SkImage_Gpu.h" 18 #include "SkImage_Gpu.h"
18 #include "SkMipMap.h" 19 #include "SkMipMap.h"
19 #include "SkPixelRef.h" 20 #include "SkPixelRef.h"
20 21
22 namespace {
23 bool shouldUseMipMaps(const SkImage::DeferredTextureImageUsageParams & param) {
24 bool shouldUseMipMaps = false;
25
26 // Use mipmaps if either
27 // 1.) it is a perspective matrix, or
28 // 2.) the quality is med/high and the scale is < 1
29 if (param.fMatrix.hasPerspective()) {
30 shouldUseMipMaps = true;
31 }
32 if (param.fQuality == kMedium_SkFilterQuality ||
33 param.fQuality == kHigh_SkFilterQuality) {
34 SkScalar minAxisScale = param.fMatrix.getMinScale();
35 if (minAxisScale != -1.f && minAxisScale < 1.f) {
36 shouldUseMipMaps = true;
37 }
38 }
39
40 return shouldUseMipMaps;
41 }
42 }
43
21 SkImage_Gpu::SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType at, GrText ure* tex, 44 SkImage_Gpu::SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType at, GrText ure* tex,
22 sk_sp<SkColorSpace> colorSpace, SkBudgeted budgeted) 45 sk_sp<SkColorSpace> colorSpace, SkBudgeted budgeted)
23 : INHERITED(w, h, uniqueID) 46 : INHERITED(w, h, uniqueID)
24 , fTexture(SkRef(tex)) 47 , fTexture(SkRef(tex))
25 , fAlphaType(at) 48 , fAlphaType(at)
26 , fBudgeted(budgeted) 49 , fBudgeted(budgeted)
27 , fColorSpace(std::move(colorSpace)) 50 , fColorSpace(std::move(colorSpace))
28 , fAddedRasterVersionToCache(false) 51 , fAddedRasterVersionToCache(false)
29 { 52 {
30 SkASSERT(tex->width() == w); 53 SkASSERT(tex->width() == w);
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 378 }
356 379
357 //////////////////////////////////////////////////////////////////////////////// /////////////////// 380 //////////////////////////////////////////////////////////////////////////////// ///////////////////
358 381
359 class DeferredTextureImage { 382 class DeferredTextureImage {
360 public: 383 public:
361 SkImage* newImage(GrContext* context, SkBudgeted) const; 384 SkImage* newImage(GrContext* context, SkBudgeted) const;
362 385
363 private: 386 private:
364 uint32_t fContextUniqueID; 387 uint32_t fContextUniqueID;
388 // Right now, the gamma treatment is only considered when generating mipmaps
389 SkSourceGammaTreatment fGammaTreatment;
365 struct MipMapLevelData { 390 struct MipMapLevelData {
366 void* fPixelData; 391 void* fPixelData;
367 size_t fRowBytes; 392 size_t fRowBytes;
368 }; 393 };
369 struct Data { 394 struct Data {
370 SkImageInfo fInfo; 395 SkImageInfo fInfo;
371 int fColorTableCnt; 396 int fColorTableCnt;
372 uint32_t* fColorTableData; 397 uint32_t* fColorTableData;
373 int fMipMapLevelCount; 398 int fMipMapLevelCount;
374 // The fMipMapLevelData array may contain more than 1 element. 399 // The fMipMapLevelData array may contain more than 1 element.
375 // It contains fMipMapLevelCount elements. 400 // It contains fMipMapLevelCount elements.
376 // That means this struct's size is not known at compile-time. 401 // That means this struct's size is not known at compile-time.
377 MipMapLevelData fMipMapLevelData[1]; 402 MipMapLevelData fMipMapLevelData[1];
378 }; 403 };
379 Data fData; 404 Data fData;
380 405
381 friend class SkImage; 406 friend class SkImage;
382 }; 407 };
383 408
384 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox y, 409 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox y,
385 const DeferredTextureImageUsageParam s params[], 410 const DeferredTextureImageUsageParam s params[],
386 int paramCnt, void* buffer) const { 411 int paramCnt, void* buffer,
412 SkSourceGammaTreatment gammaTreatmen t) const {
387 // Extract relevant min/max values from the params array. 413 // Extract relevant min/max values from the params array.
388 int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel; 414 int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
389 SkFilterQuality highestFilterQuality = params[0].fQuality; 415 SkFilterQuality highestFilterQuality = params[0].fQuality;
416 bool useMipMaps = shouldUseMipMaps(params[0]);
390 for (int i = 1; i < paramCnt; ++i) { 417 for (int i = 1; i < paramCnt; ++i) {
391 if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel) 418 if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel)
392 lowestPreScaleMipLevel = params[i].fPreScaleMipLevel; 419 lowestPreScaleMipLevel = params[i].fPreScaleMipLevel;
393 if (highestFilterQuality < params[i].fQuality) 420 if (highestFilterQuality < params[i].fQuality)
394 highestFilterQuality = params[i].fQuality; 421 highestFilterQuality = params[i].fQuality;
422 useMipMaps |= shouldUseMipMaps(params[i]);
395 } 423 }
396 424
397 const bool fillMode = SkToBool(buffer); 425 const bool fillMode = SkToBool(buffer);
398 if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) { 426 if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) {
399 return 0; 427 return 0;
400 } 428 }
401 429
402 // Calculate scaling parameters. 430 // Calculate scaling parameters.
403 bool isScaled = lowestPreScaleMipLevel != 0; 431 bool isScaled = lowestPreScaleMipLevel != 0;
404 432
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 return 0; 482 return 0;
455 } 483 }
456 } else { 484 } else {
457 if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHi nt)) { 485 if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHi nt)) {
458 return 0; 486 return 0;
459 } 487 }
460 } 488 }
461 SkASSERT(!pixmap.ctable()); 489 SkASSERT(!pixmap.ctable());
462 } 490 }
463 } 491 }
492 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaTyp e;
464 int mipMapLevelCount = 1; 493 int mipMapLevelCount = 1;
494 if (useMipMaps) {
495 // SkMipMap only deals with the mipmap levels it generates, which does
496 // not include the base level.
497 // That means it generates and holds levels 1-x instead of 0-x.
498 // So the total mipmap level count is 1 more than what
499 // SkMipMap::ComputeLevelCount returns.
500 mipMapLevelCount = SkMipMap::ComputeLevelCount(scaledSize.width(), scale dSize.height()) + 1;
501
502 // We already initialized pixelSize to the size of the base level.
503 // SkMipMap will generate the extra mipmap levels. Their sizes need to
504 // be added to the total.
505 // Index 0 here does not refer to the base mipmap level -- it is
506 // SkMipMap's first generated mipmap level (level 1).
507 for (int currentMipMapLevelIndex = mipMapLevelCount - 1; currentMipMapLe velIndex >= 0;
508 currentMipMapLevelIndex--) {
509 SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), sca ledSize.height(),
510 currentMipMapLevelIndex );
511 SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.f Height, at);
512 pixelSize += SkAlign8(SkAutoPixmapStorage::AllocSize(mipInfo, nullpt r));
513 }
514 }
465 size_t size = 0; 515 size_t size = 0;
466 size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage)); 516 size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage));
467 size += dtiSize; 517 size += dtiSize;
468 size += mipMapLevelCount * sizeof(DeferredTextureImage::MipMapLevelData); 518 size += mipMapLevelCount * sizeof(DeferredTextureImage::MipMapLevelData);
469 size_t pixelOffset = size; 519 size_t pixelOffset = size;
470 size += pixelSize; 520 size += pixelSize;
471 size_t ctOffset = size; 521 size_t ctOffset = size;
472 size += ctSize; 522 size += ctSize;
473 if (!fillMode) { 523 if (!fillMode) {
474 return size; 524 return size;
475 } 525 }
476 intptr_t bufferAsInt = reinterpret_cast<intptr_t>(buffer); 526 intptr_t bufferAsInt = reinterpret_cast<intptr_t>(buffer);
477 void* pixels = reinterpret_cast<void*>(bufferAsInt + pixelOffset); 527 void* pixels = reinterpret_cast<void*>(bufferAsInt + pixelOffset);
478 SkPMColor* ct = nullptr; 528 SkPMColor* ct = nullptr;
479 if (ctSize) { 529 if (ctSize) {
480 ct = reinterpret_cast<SkPMColor*>(bufferAsInt + ctOffset); 530 ct = reinterpret_cast<SkPMColor*>(bufferAsInt + ctOffset);
481 } 531 }
482 532
483 memcpy(pixels, pixmap.addr(), pixmap.getSafeSize()); 533 memcpy(pixels, pixmap.addr(), pixmap.getSafeSize());
484 if (ctSize) { 534 if (ctSize) {
485 memcpy(ct, pixmap.ctable()->readColors(), ctSize); 535 memcpy(ct, pixmap.ctable()->readColors(), ctSize);
486 } 536 }
487 537
488 SkASSERT(info == pixmap.info()); 538 SkASSERT(info == pixmap.info());
489 size_t rowBytes = pixmap.rowBytes(); 539 size_t rowBytes = pixmap.rowBytes();
490 DeferredTextureImage* dti = new (buffer) DeferredTextureImage(); 540 DeferredTextureImage* dti = new (buffer) DeferredTextureImage();
491 dti->fContextUniqueID = proxy.fContextUniqueID; 541 dti->fContextUniqueID = proxy.fContextUniqueID;
542 dti->fGammaTreatment = gammaTreatment;
492 dti->fData.fInfo = info; 543 dti->fData.fInfo = info;
493 dti->fData.fColorTableCnt = ctCount; 544 dti->fData.fColorTableCnt = ctCount;
494 dti->fData.fColorTableData = ct; 545 dti->fData.fColorTableData = ct;
495 dti->fData.fMipMapLevelCount = mipMapLevelCount; 546 dti->fData.fMipMapLevelCount = mipMapLevelCount;
496 dti->fData.fMipMapLevelData[0].fPixelData = pixels; 547 dti->fData.fMipMapLevelData[0].fPixelData = pixels;
497 dti->fData.fMipMapLevelData[0].fRowBytes = rowBytes; 548 dti->fData.fMipMapLevelData[0].fRowBytes = rowBytes;
549
550 // Fill in the mipmap levels if they exist
551 intptr_t mipLevelPtr = bufferAsInt + pixelOffset + SkAlign8(SkAutoPixmapStor age::AllocSize(
552 info, nullptr));
553 if (useMipMaps) {
554 SkAutoTDelete<SkMipMap> mipmaps(SkMipMap::Build(pixmap, gammaTreatment, nullptr));
555 // SkMipMap holds only the mipmap levels it generates.
556 // A programmer can use the data they provided to SkMipMap::Build as lev el 0.
557 // So the SkMipMap provides levels 1-x but it stores them in its own
558 // range 0-(x-1).
559 for (int generatedMipLevelIndex = 0; generatedMipLevelIndex < mipMapLeve lCount - 1;
560 generatedMipLevelIndex++) {
561 SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), sca ledSize.height(),
562 generatedMipLevelIndex) ;
563 SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.f Height, at);
564 SkMipMap::Level mipLevel;
565 mipmaps->getLevel(generatedMipLevelIndex, &mipLevel);
566 memcpy(reinterpret_cast<void*>(mipLevelPtr), mipLevel.fPixmap.addr() ,
567 mipLevel.fPixmap.getSafeSize());
568 dti->fData.fMipMapLevelData[generatedMipLevelIndex + 1].fPixelData =
569 reinterpret_cast<void*>(mipLevelPtr);
570 dti->fData.fMipMapLevelData[generatedMipLevelIndex + 1].fRowBytes =
571 mipLevel.fPixmap.rowBytes();
572 mipLevelPtr += SkAlign8(mipLevel.fPixmap.getSafeSize());
573 }
574 }
498 return size; 575 return size;
499 } 576 }
500 577
501 sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con st void* data, 578 sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con st void* data,
502 SkBudgeted budgeted) { 579 SkBudgeted budgeted) {
503 if (!data) { 580 if (!data) {
504 return nullptr; 581 return nullptr;
505 } 582 }
506 const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImag e*>(data); 583 const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImag e*>(data);
507 584
508 if (!context || context->uniqueID() != dti->fContextUniqueID) { 585 if (!context || context->uniqueID() != dti->fContextUniqueID) {
509 return nullptr; 586 return nullptr;
510 } 587 }
511 SkAutoTUnref<SkColorTable> colorTable; 588 SkAutoTUnref<SkColorTable> colorTable;
512 if (dti->fData.fColorTableCnt) { 589 if (dti->fData.fColorTableCnt) {
513 SkASSERT(dti->fData.fColorTableData); 590 SkASSERT(dti->fData.fColorTableData);
514 colorTable.reset(new SkColorTable(dti->fData.fColorTableData, dti->fData .fColorTableCnt)); 591 colorTable.reset(new SkColorTable(dti->fData.fColorTableData, dti->fData .fColorTableCnt));
515 } 592 }
516 SkASSERT(dti->fData.fMipMapLevelCount == 1); 593 int mipLevelCount = dti->fData.fMipMapLevelCount;
517 SkPixmap pixmap; 594 SkASSERT(mipLevelCount >= 1);
518 pixmap.reset(dti->fData.fInfo, dti->fData.fMipMapLevelData[0].fPixelData, 595 if (mipLevelCount == 1) {
519 dti->fData.fMipMapLevelData[0].fRowBytes, colorTable.get()); 596 SkPixmap pixmap;
520 return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted); 597 pixmap.reset(dti->fData.fInfo, dti->fData.fMipMapLevelData[0].fPixelData ,
598 dti->fData.fMipMapLevelData[0].fRowBytes, colorTable.get()) ;
599 return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
600 } else {
601 SkAutoTDeleteArray<GrMipLevel> texels(new GrMipLevel[mipLevelCount]);
602 for (int i = 0; i < mipLevelCount; i++) {
603 texels[i].fPixels = dti->fData.fMipMapLevelData[i].fPixelData;
604 texels[i].fRowBytes = dti->fData.fMipMapLevelData[i].fRowBytes;
605 }
606
607 return SkImage::MakeTextureFromMipMap(context, dti->fData.fInfo, texels. get(),
608 mipLevelCount, SkBudgeted::kYes,
609 dti->fGammaTreatment);
610 }
521 } 611 }
522 612
523 //////////////////////////////////////////////////////////////////////////////// /////////////////// 613 //////////////////////////////////////////////////////////////////////////////// ///////////////////
524 614
525 GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) { 615 GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) {
526 GrContext* ctx = src->getContext(); 616 GrContext* ctx = src->getContext();
527 617
528 GrSurfaceDesc desc = src->desc(); 618 GrSurfaceDesc desc = src->desc();
529 GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, nullp tr, 0); 619 GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, nullp tr, 0);
530 if (!dst) { 620 if (!dst) {
531 return nullptr; 621 return nullptr;
532 } 622 }
533 623
534 const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight); 624 const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight);
535 const SkIPoint dstP = SkIPoint::Make(0, 0); 625 const SkIPoint dstP = SkIPoint::Make(0, 0);
536 ctx->copySurface(dst, src, srcR, dstP); 626 ctx->copySurface(dst, src, srcR, dstP);
537 ctx->flushSurfaceWrites(dst); 627 ctx->flushSurfaceWrites(dst);
538 return dst; 628 return dst;
539 } 629 }
540 630
541 sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info, 631 sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info,
542 const GrMipLevel* texels, int mipL evelCount, 632 const GrMipLevel* texels, int mipL evelCount,
543 SkBudgeted budgeted) { 633 SkBudgeted budgeted,
634 SkSourceGammaTreatment gammaTreatm ent) {
544 if (!ctx) { 635 if (!ctx) {
545 return nullptr; 636 return nullptr;
546 } 637 }
547 SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, m ipLevelCount)); 638 SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, m ipLevelCount));
548 if (!texture) { 639 if (!texture) {
549 return nullptr; 640 return nullptr;
550 } 641 }
642 texture->texturePriv().setGammaTreatment(gammaTreatment);
551 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNew ImageUniqueID, 643 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNew ImageUniqueID,
552 info.alphaType(), texture, sk_ref_sp(info.col orSpace()), 644 info.alphaType(), texture, sk_ref_sp(info.col orSpace()),
553 budgeted); 645 budgeted);
554 } 646 }
OLDNEW
« gm/deferredtextureimage.cpp ('K') | « src/image/SkImage.cpp ('k') | tests/ImageTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698