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

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: Merged in serialization of color space info. Created 4 years, 4 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) {
bsalomon 2016/07/29 14:12:35 For file-local functions we use static over anonym
cblume 2016/07/29 20:14:13 Done.
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 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 //////////////////////////////////////////////////////////////////////////////// /////////////////// 381 //////////////////////////////////////////////////////////////////////////////// ///////////////////
359 382
360 namespace { 383 namespace {
361 struct MipMapLevelData { 384 struct MipMapLevelData {
362 void* fPixelData; 385 void* fPixelData;
363 size_t fRowBytes; 386 size_t fRowBytes;
364 }; 387 };
365 388
366 struct DeferredTextureImage { 389 struct DeferredTextureImage {
367 uint32_t fContextUniqueID; 390 uint32_t fContextUniqueID;
391 // Right now, the gamma treatment is only considered when generating mipmaps
392 SkSourceGammaTreatment fGammaTreatment;
bsalomon 2016/07/29 14:12:35 Let's either line up all the members or make them
cblume 2016/07/29 20:14:13 Done.
368 // We don't store a SkImageInfo because it contains a ref-counted SkColorSpa ce. 393 // We don't store a SkImageInfo because it contains a ref-counted SkColorSpa ce.
369 int fWidth; 394 int fWidth;
370 int fHeight; 395 int fHeight;
371 SkColorType fColorType; 396 SkColorType fColorType;
372 SkAlphaType fAlphaType; 397 SkAlphaType fAlphaType;
373 void* fColorSpace; 398 void* fColorSpace;
374 size_t fColorSpaceSize; 399 size_t fColorSpaceSize;
375 int fColorTableCnt; 400 int fColorTableCnt;
376 uint32_t* fColorTableData; 401 uint32_t* fColorTableData;
377 int fMipMapLevelCount; 402 int fMipMapLevelCount;
378 // The fMipMapLevelData array may contain more than 1 element. 403 // The fMipMapLevelData array may contain more than 1 element.
379 // It contains fMipMapLevelCount elements. 404 // It contains fMipMapLevelCount elements.
380 // That means this struct's size is not known at compile-time. 405 // That means this struct's size is not known at compile-time.
381 MipMapLevelData fMipMapLevelData[1]; 406 MipMapLevelData fMipMapLevelData[1];
382 }; 407 };
383 } // anonymous namespace 408 } // anonymous namespace
384 409
385 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox y, 410 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox y,
386 const DeferredTextureImageUsageParam s params[], 411 const DeferredTextureImageUsageParam s params[],
387 int paramCnt, void* buffer) const { 412 int paramCnt, void* buffer,
413 SkSourceGammaTreatment gammaTreatmen t) const {
388 // Extract relevant min/max values from the params array. 414 // Extract relevant min/max values from the params array.
389 int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel; 415 int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
390 SkFilterQuality highestFilterQuality = params[0].fQuality; 416 SkFilterQuality highestFilterQuality = params[0].fQuality;
417 bool useMipMaps = shouldUseMipMaps(params[0]);
391 for (int i = 1; i < paramCnt; ++i) { 418 for (int i = 1; i < paramCnt; ++i) {
392 if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel) 419 if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel)
393 lowestPreScaleMipLevel = params[i].fPreScaleMipLevel; 420 lowestPreScaleMipLevel = params[i].fPreScaleMipLevel;
394 if (highestFilterQuality < params[i].fQuality) 421 if (highestFilterQuality < params[i].fQuality)
395 highestFilterQuality = params[i].fQuality; 422 highestFilterQuality = params[i].fQuality;
423 useMipMaps |= shouldUseMipMaps(params[i]);
396 } 424 }
397 425
398 const bool fillMode = SkToBool(buffer); 426 const bool fillMode = SkToBool(buffer);
399 if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) { 427 if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) {
400 return 0; 428 return 0;
401 } 429 }
402 430
403 // Calculate scaling parameters. 431 // Calculate scaling parameters.
404 bool isScaled = lowestPreScaleMipLevel != 0; 432 bool isScaled = lowestPreScaleMipLevel != 0;
405 433
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 return 0; 483 return 0;
456 } 484 }
457 } else { 485 } else {
458 if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHi nt)) { 486 if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHi nt)) {
459 return 0; 487 return 0;
460 } 488 }
461 } 489 }
462 SkASSERT(!pixmap.ctable()); 490 SkASSERT(!pixmap.ctable());
463 } 491 }
464 } 492 }
493 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaTyp e;
bsalomon 2016/07/29 14:12:35 I believe SkImage_Gpu now stores an alpha type.
cblume 2016/07/29 20:14:13 This code is inside SkImage::getDeferred..., not S
bsalomon 2016/08/09 19:02:08 Nope, my suggestion was wrong
465 int mipMapLevelCount = 1; 494 int mipMapLevelCount = 1;
495 if (useMipMaps) {
496 // SkMipMap only deals with the mipmap levels it generates, which does
497 // not include the base level.
498 // That means it generates and holds levels 1-x instead of 0-x.
499 // So the total mipmap level count is 1 more than what
500 // SkMipMap::ComputeLevelCount returns.
501 mipMapLevelCount = SkMipMap::ComputeLevelCount(scaledSize.width(), scale dSize.height()) + 1;
502
503 // We already initialized pixelSize to the size of the base level.
504 // SkMipMap will generate the extra mipmap levels. Their sizes need to
505 // be added to the total.
506 // Index 0 here does not refer to the base mipmap level -- it is
507 // SkMipMap's first generated mipmap level (level 1).
508 for (int currentMipMapLevelIndex = mipMapLevelCount - 1; currentMipMapLe velIndex >= 0;
509 currentMipMapLevelIndex--) {
510 SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), sca ledSize.height(),
511 currentMipMapLevelIndex );
512 SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.f Height, at);
513 pixelSize += SkAlign8(SkAutoPixmapStorage::AllocSize(mipInfo, nullpt r));
514 }
515 }
466 size_t size = 0; 516 size_t size = 0;
467 size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage)); 517 size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage));
468 size += dtiSize; 518 size += dtiSize;
469 size += mipMapLevelCount * sizeof(MipMapLevelData); 519 size += mipMapLevelCount * sizeof(MipMapLevelData);
470 size_t pixelOffset = size; 520 size_t pixelOffset = size;
471 size += pixelSize; 521 size += pixelSize;
472 size_t ctOffset = size; 522 size_t ctOffset = size;
473 size += ctSize; 523 size += ctSize;
474 size_t colorSpaceOffset = 0; 524 size_t colorSpaceOffset = 0;
475 size_t colorSpaceSize = 0; 525 size_t colorSpaceSize = 0;
(...skipping 13 matching lines...) Expand all
489 } 539 }
490 540
491 memcpy(pixels, pixmap.addr(), pixmap.getSafeSize()); 541 memcpy(pixels, pixmap.addr(), pixmap.getSafeSize());
492 if (ctSize) { 542 if (ctSize) {
493 memcpy(ct, pixmap.ctable()->readColors(), ctSize); 543 memcpy(ct, pixmap.ctable()->readColors(), ctSize);
494 } 544 }
495 545
496 SkASSERT(info == pixmap.info()); 546 SkASSERT(info == pixmap.info());
497 size_t rowBytes = pixmap.rowBytes(); 547 size_t rowBytes = pixmap.rowBytes();
498 DeferredTextureImage* dti = new (buffer) DeferredTextureImage(); 548 DeferredTextureImage* dti = new (buffer) DeferredTextureImage();
549 dti->fGammaTreatment = gammaTreatment;
499 dti->fContextUniqueID = proxy.fContextUniqueID; 550 dti->fContextUniqueID = proxy.fContextUniqueID;
500 dti->fWidth = info.width(); 551 dti->fWidth = info.width();
501 dti->fHeight = info.height(); 552 dti->fHeight = info.height();
502 dti->fColorType = info.colorType(); 553 dti->fColorType = info.colorType();
503 dti->fAlphaType = info.alphaType(); 554 dti->fAlphaType = info.alphaType();
504 dti->fColorTableCnt = ctCount; 555 dti->fColorTableCnt = ctCount;
505 dti->fColorTableData = ct; 556 dti->fColorTableData = ct;
506 dti->fMipMapLevelCount = mipMapLevelCount; 557 dti->fMipMapLevelCount = mipMapLevelCount;
507 dti->fMipMapLevelData[0].fPixelData = pixels; 558 dti->fMipMapLevelData[0].fPixelData = pixels;
508 dti->fMipMapLevelData[0].fRowBytes = rowBytes; 559 dti->fMipMapLevelData[0].fRowBytes = rowBytes;
509 if (colorSpaceSize) { 560 if (colorSpaceSize) {
510 dti->fColorSpace = reinterpret_cast<void*>(bufferAsInt + colorSpaceOffse t); 561 dti->fColorSpace = reinterpret_cast<void*>(bufferAsInt + colorSpaceOffse t);
511 dti->fColorSpaceSize = colorSpaceSize; 562 dti->fColorSpaceSize = colorSpaceSize;
512 info.colorSpace()->writeToMemory(dti->fColorSpace); 563 info.colorSpace()->writeToMemory(dti->fColorSpace);
513 } else { 564 } else {
514 dti->fColorSpace = nullptr; 565 dti->fColorSpace = nullptr;
515 dti->fColorSpaceSize = 0; 566 dti->fColorSpaceSize = 0;
516 } 567 }
568
569 // Fill in the mipmap levels if they exist
570 intptr_t mipLevelPtr = bufferAsInt + pixelOffset + SkAlign8(SkAutoPixmapStor age::AllocSize(
571 info, nullptr));
572 if (useMipMaps) {
573 SkAutoTDelete<SkMipMap> mipmaps(SkMipMap::Build(pixmap, gammaTreatment, nullptr));
574 // SkMipMap holds only the mipmap levels it generates.
575 // A programmer can use the data they provided to SkMipMap::Build as lev el 0.
576 // So the SkMipMap provides levels 1-x but it stores them in its own
577 // range 0-(x-1).
578 for (int generatedMipLevelIndex = 0; generatedMipLevelIndex < mipMapLeve lCount - 1;
579 generatedMipLevelIndex++) {
580 SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), sca ledSize.height(),
581 generatedMipLevelIndex) ;
582 SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.f Height, at);
583 SkMipMap::Level mipLevel;
584 mipmaps->getLevel(generatedMipLevelIndex, &mipLevel);
585 memcpy(reinterpret_cast<void*>(mipLevelPtr), mipLevel.fPixmap.addr() ,
586 mipLevel.fPixmap.getSafeSize());
587 dti->fMipMapLevelData[generatedMipLevelIndex + 1].fPixelData =
588 reinterpret_cast<void*>(mipLevelPtr);
589 dti->fMipMapLevelData[generatedMipLevelIndex + 1].fRowBytes =
590 mipLevel.fPixmap.rowBytes();
591 mipLevelPtr += SkAlign8(mipLevel.fPixmap.getSafeSize());
592 }
593 }
517 return size; 594 return size;
518 } 595 }
519 596
520 sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con st void* data, 597 sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con st void* data,
521 SkBudgeted budgeted) { 598 SkBudgeted budgeted) {
522 if (!data) { 599 if (!data) {
523 return nullptr; 600 return nullptr;
524 } 601 }
525 const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImag e*>(data); 602 const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImag e*>(data);
526 603
527 if (!context || context->uniqueID() != dti->fContextUniqueID) { 604 if (!context || context->uniqueID() != dti->fContextUniqueID) {
528 return nullptr; 605 return nullptr;
529 } 606 }
530 SkAutoTUnref<SkColorTable> colorTable; 607 SkAutoTUnref<SkColorTable> colorTable;
531 if (dti->fColorTableCnt) { 608 if (dti->fColorTableCnt) {
532 SkASSERT(dti->fColorTableData); 609 SkASSERT(dti->fColorTableData);
533 colorTable.reset(new SkColorTable(dti->fColorTableData, dti->fColorTable Cnt)); 610 colorTable.reset(new SkColorTable(dti->fColorTableData, dti->fColorTable Cnt));
534 } 611 }
535 SkASSERT(dti->fMipMapLevelCount == 1); 612 int mipLevelCount = dti->fMipMapLevelCount;
613 SkASSERT(mipLevelCount >= 1);
536 sk_sp<SkColorSpace> colorSpace; 614 sk_sp<SkColorSpace> colorSpace;
537 if (dti->fColorSpaceSize) { 615 if (dti->fColorSpaceSize) {
538 colorSpace = SkColorSpace::Deserialize(dti->fColorSpace, dti->fColorSpac eSize); 616 colorSpace = SkColorSpace::Deserialize(dti->fColorSpace, dti->fColorSpac eSize);
539 } 617 }
540 SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight, 618 SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight,
541 dti->fColorType, dti->fAlphaType, color Space); 619 dti->fColorType, dti->fAlphaType, color Space);
542 SkPixmap pixmap; 620 if (mipLevelCount == 1) {
543 pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData, 621 SkPixmap pixmap;
544 dti->fMipMapLevelData[0].fRowBytes, colorTable.get()); 622 pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData,
545 return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted); 623 dti->fMipMapLevelData[0].fRowBytes, colorTable.get());
624 return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
625 } else {
626 SkAutoTDeleteArray<GrMipLevel> texels(new GrMipLevel[mipLevelCount]);
627 for (int i = 0; i < mipLevelCount; i++) {
628 texels[i].fPixels = dti->fMipMapLevelData[i].fPixelData;
629 texels[i].fRowBytes = dti->fMipMapLevelData[i].fRowBytes;
630 }
631
632 return SkImage::MakeTextureFromMipMap(context, info, texels.get(),
633 mipLevelCount, SkBudgeted::kYes,
634 dti->fGammaTreatment);
635 }
546 } 636 }
547 637
548 //////////////////////////////////////////////////////////////////////////////// /////////////////// 638 //////////////////////////////////////////////////////////////////////////////// ///////////////////
549 639
550 GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) { 640 GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) {
551 GrContext* ctx = src->getContext(); 641 GrContext* ctx = src->getContext();
552 642
553 GrSurfaceDesc desc = src->desc(); 643 GrSurfaceDesc desc = src->desc();
554 GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, nullp tr, 0); 644 GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, nullp tr, 0);
555 if (!dst) { 645 if (!dst) {
556 return nullptr; 646 return nullptr;
557 } 647 }
558 648
559 const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight); 649 const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight);
560 const SkIPoint dstP = SkIPoint::Make(0, 0); 650 const SkIPoint dstP = SkIPoint::Make(0, 0);
561 ctx->copySurface(dst, src, srcR, dstP); 651 ctx->copySurface(dst, src, srcR, dstP);
562 ctx->flushSurfaceWrites(dst); 652 ctx->flushSurfaceWrites(dst);
563 return dst; 653 return dst;
564 } 654 }
565 655
566 sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info, 656 sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info,
567 const GrMipLevel* texels, int mipL evelCount, 657 const GrMipLevel* texels, int mipL evelCount,
568 SkBudgeted budgeted) { 658 SkBudgeted budgeted,
659 SkSourceGammaTreatment gammaTreatm ent) {
569 if (!ctx) { 660 if (!ctx) {
570 return nullptr; 661 return nullptr;
571 } 662 }
572 SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, m ipLevelCount)); 663 SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, m ipLevelCount));
573 if (!texture) { 664 if (!texture) {
574 return nullptr; 665 return nullptr;
575 } 666 }
667 texture->texturePriv().setGammaTreatment(gammaTreatment);
576 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNew ImageUniqueID, 668 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNew ImageUniqueID,
577 info.alphaType(), texture, sk_ref_sp(info.col orSpace()), 669 info.alphaType(), texture, sk_ref_sp(info.col orSpace()),
578 budgeted); 670 budgeted);
579 } 671 }
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