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

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

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

Powered by Google App Engine
This is Rietveld 408576698