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

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: Using scaled size. 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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 } 369 }
347 370
348 //////////////////////////////////////////////////////////////////////////////// /////////////////// 371 //////////////////////////////////////////////////////////////////////////////// ///////////////////
349 372
350 class DeferredTextureImage { 373 class DeferredTextureImage {
351 public: 374 public:
352 SkImage* newImage(GrContext* context, SkBudgeted) const; 375 SkImage* newImage(GrContext* context, SkBudgeted) const;
353 376
354 private: 377 private:
355 uint32_t fContextUniqueID; 378 uint32_t fContextUniqueID;
379 // Right now, the gamma treatment is only considered when generating mipmaps
380 SkSourceGammaTreatment fGammaTreatment;
356 struct MipMapLevelData { 381 struct MipMapLevelData {
357 void* fPixelData; 382 void* fPixelData;
358 size_t fRowBytes; 383 size_t fRowBytes;
359 }; 384 };
360 struct Data { 385 struct Data {
361 SkImageInfo fInfo; 386 SkImageInfo fInfo;
362 int fColorTableCnt; 387 int fColorTableCnt;
363 uint32_t* fColorTableData; 388 uint32_t* fColorTableData;
364 int fMipMapLevelCount; 389 int fMipMapLevelCount;
365 // The fMipMapLevelData array may contain more than 1 element. 390 // The fMipMapLevelData array may contain more than 1 element.
366 // It contains fMipMapLevelCount elements. 391 // It contains fMipMapLevelCount elements.
367 // That means this struct's size is not known at compile-time. 392 // That means this struct's size is not known at compile-time.
368 MipMapLevelData fMipMapLevelData[1]; 393 MipMapLevelData fMipMapLevelData[1];
369 }; 394 };
370 Data fData; 395 Data fData;
371 396
372 friend class SkImage; 397 friend class SkImage;
373 }; 398 };
374 399
375 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox y, 400 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox y,
376 const DeferredTextureImageUsageParam s params[], 401 const DeferredTextureImageUsageParam s params[],
377 int paramCnt, void* buffer) const { 402 int paramCnt, void* buffer,
403 SkSourceGammaTreatment gammaTreatmen t) const {
378 // Extract relevant min/max values from the params array. 404 // Extract relevant min/max values from the params array.
379 int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel; 405 int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
380 SkFilterQuality highestFilterQuality = params[0].fQuality; 406 SkFilterQuality highestFilterQuality = params[0].fQuality;
407 bool useMipMaps = shouldUseMipMaps(params[0]);
381 for (int i = 1; i < paramCnt; ++i) { 408 for (int i = 1; i < paramCnt; ++i) {
382 if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel) 409 if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel)
383 lowestPreScaleMipLevel = params[i].fPreScaleMipLevel; 410 lowestPreScaleMipLevel = params[i].fPreScaleMipLevel;
384 if (highestFilterQuality < params[i].fQuality) 411 if (highestFilterQuality < params[i].fQuality)
385 highestFilterQuality = params[i].fQuality; 412 highestFilterQuality = params[i].fQuality;
413 useMipMaps |= shouldUseMipMaps(params[i]);
386 } 414 }
387 415
388 const bool fillMode = SkToBool(buffer); 416 const bool fillMode = SkToBool(buffer);
389 if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) { 417 if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) {
390 return 0; 418 return 0;
391 } 419 }
392 420
393 // Calculate scaling parameters. 421 // Calculate scaling parameters.
394 bool isScaled = lowestPreScaleMipLevel != 0; 422 bool isScaled = lowestPreScaleMipLevel != 0;
395 423
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 return 0; 473 return 0;
446 } 474 }
447 } else { 475 } else {
448 if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHi nt)) { 476 if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHi nt)) {
449 return 0; 477 return 0;
450 } 478 }
451 } 479 }
452 SkASSERT(!pixmap.ctable()); 480 SkASSERT(!pixmap.ctable());
453 } 481 }
454 } 482 }
483 SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaTyp e;
455 int mipMapLevelCount = 1; 484 int mipMapLevelCount = 1;
485 if (useMipMaps) {
486 // SkMipMap only deals with the mipmap levels it generates, which does
487 // not include the base level.
488 // That means it generates and holds levels 1-x instead of 0-x.
489 // So the total mipmap level count is 1 more than what
490 // SkMipMap::ComputeLevelCount returns.
491 mipMapLevelCount = SkMipMap::ComputeLevelCount(scaledSize.width(), scale dSize.height()) + 1;
492
493 // We already initialized pixelSize to the size of the base level.
494 // SkMipMap will generate the extra mipmap levels. Their sizes need to
495 // be added to the total.
496 // Index 0 here does not refer to the base mipmap level -- it is
497 // SkMipMap's first generated mipmap level (level 1).
498 for (int currentMipMapLevelIndex = mipMapLevelCount - 1; currentMipMapLe velIndex >= 0;
499 currentMipMapLevelIndex--) {
500 SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), sca ledSize.height(),
501 currentMipMapLevelIndex );
502 SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.f Height, at);
503 pixelSize += SkAlign8(SkAutoPixmapStorage::AllocSize(mipInfo, nullpt r));
504 }
505 }
456 size_t size = 0; 506 size_t size = 0;
457 size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage)); 507 size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage));
458 size += dtiSize; 508 size += dtiSize;
459 size += mipMapLevelCount * sizeof(DeferredTextureImage::MipMapLevelData); 509 size += mipMapLevelCount * sizeof(DeferredTextureImage::MipMapLevelData);
460 size_t pixelOffset = size; 510 size_t pixelOffset = size;
461 size += pixelSize; 511 size += pixelSize;
462 size_t ctOffset = size; 512 size_t ctOffset = size;
463 size += ctSize; 513 size += ctSize;
464 if (!fillMode) { 514 if (!fillMode) {
465 return size; 515 return size;
466 } 516 }
467 intptr_t bufferAsInt = reinterpret_cast<intptr_t>(buffer); 517 intptr_t bufferAsInt = reinterpret_cast<intptr_t>(buffer);
468 void* pixels = reinterpret_cast<void*>(bufferAsInt + pixelOffset); 518 void* pixels = reinterpret_cast<void*>(bufferAsInt + pixelOffset);
469 SkPMColor* ct = nullptr; 519 SkPMColor* ct = nullptr;
470 if (ctSize) { 520 if (ctSize) {
471 ct = reinterpret_cast<SkPMColor*>(bufferAsInt + ctOffset); 521 ct = reinterpret_cast<SkPMColor*>(bufferAsInt + ctOffset);
472 } 522 }
473 523
474 memcpy(pixels, pixmap.addr(), pixmap.getSafeSize()); 524 memcpy(pixels, pixmap.addr(), pixmap.getSafeSize());
475 if (ctSize) { 525 if (ctSize) {
476 memcpy(ct, pixmap.ctable()->readColors(), ctSize); 526 memcpy(ct, pixmap.ctable()->readColors(), ctSize);
477 } 527 }
478 528
479 SkASSERT(info == pixmap.info()); 529 SkASSERT(info == pixmap.info());
480 size_t rowBytes = pixmap.rowBytes(); 530 size_t rowBytes = pixmap.rowBytes();
481 DeferredTextureImage* dti = new (buffer) DeferredTextureImage(); 531 DeferredTextureImage* dti = new (buffer) DeferredTextureImage();
482 dti->fContextUniqueID = proxy.fContextUniqueID; 532 dti->fContextUniqueID = proxy.fContextUniqueID;
533 dti->fGammaTreatment = gammaTreatment;
483 dti->fData.fInfo = info; 534 dti->fData.fInfo = info;
484 dti->fData.fColorTableCnt = ctCount; 535 dti->fData.fColorTableCnt = ctCount;
485 dti->fData.fColorTableData = ct; 536 dti->fData.fColorTableData = ct;
486 dti->fData.fMipMapLevelCount = mipMapLevelCount; 537 dti->fData.fMipMapLevelCount = mipMapLevelCount;
487 dti->fData.fMipMapLevelData[0].fPixelData = pixels; 538 dti->fData.fMipMapLevelData[0].fPixelData = pixels;
488 dti->fData.fMipMapLevelData[0].fRowBytes = rowBytes; 539 dti->fData.fMipMapLevelData[0].fRowBytes = rowBytes;
540
541 // Fill in the mipmap levels if they exist
542 intptr_t mipLevelPtr = bufferAsInt + pixelOffset + SkAlign8(SkAutoPixmapStor age::AllocSize(
543 info, nullptr));
544 if (useMipMaps) {
545 SkAutoTDelete<SkMipMap> mipmaps(SkMipMap::Build(pixmap, gammaTreatment, nullptr));
546 // SkMipMap holds only the mipmap levels it generates.
547 // A programmer can use the data they provided to SkMipMap::Build as lev el 0.
548 // So the SkMipMap provides levels 1-x but it stores them in its own
549 // range 0-(x-1).
550 for (int generatedMipLevelIndex = 0; generatedMipLevelIndex < mipMapLeve lCount - 1;
551 generatedMipLevelIndex++) {
552 SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), sca ledSize.height(),
553 generatedMipLevelIndex) ;
554 SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.f Height, at);
555 SkMipMap::Level mipLevel;
556 mipmaps->getLevel(generatedMipLevelIndex, &mipLevel);
557 memcpy(reinterpret_cast<void*>(mipLevelPtr), mipLevel.fPixmap.addr() ,
558 mipLevel.fPixmap.getSafeSize());
559 dti->fData.fMipMapLevelData[generatedMipLevelIndex + 1].fPixelData =
560 reinterpret_cast<void*>(mipLevelPtr);
561 dti->fData.fMipMapLevelData[generatedMipLevelIndex + 1].fRowBytes =
562 mipLevel.fPixmap.rowBytes();
563 mipLevelPtr += SkAlign8(mipLevel.fPixmap.getSafeSize());
564 }
565 }
489 return size; 566 return size;
490 } 567 }
491 568
492 sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con st void* data, 569 sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con st void* data,
493 SkBudgeted budgeted) { 570 SkBudgeted budgeted) {
494 if (!data) { 571 if (!data) {
495 return nullptr; 572 return nullptr;
496 } 573 }
497 const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImag e*>(data); 574 const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImag e*>(data);
498 575
499 if (!context || context->uniqueID() != dti->fContextUniqueID) { 576 if (!context || context->uniqueID() != dti->fContextUniqueID) {
500 return nullptr; 577 return nullptr;
501 } 578 }
502 SkAutoTUnref<SkColorTable> colorTable; 579 SkAutoTUnref<SkColorTable> colorTable;
503 if (dti->fData.fColorTableCnt) { 580 if (dti->fData.fColorTableCnt) {
504 SkASSERT(dti->fData.fColorTableData); 581 SkASSERT(dti->fData.fColorTableData);
505 colorTable.reset(new SkColorTable(dti->fData.fColorTableData, dti->fData .fColorTableCnt)); 582 colorTable.reset(new SkColorTable(dti->fData.fColorTableData, dti->fData .fColorTableCnt));
506 } 583 }
507 SkASSERT(dti->fData.fMipMapLevelCount == 1); 584 int mipLevelCount = dti->fData.fMipMapLevelCount;
508 SkPixmap pixmap; 585 SkASSERT(mipLevelCount >= 1);
509 pixmap.reset(dti->fData.fInfo, dti->fData.fMipMapLevelData[0].fPixelData, 586 if (mipLevelCount == 1) {
510 dti->fData.fMipMapLevelData[0].fRowBytes, colorTable.get()); 587 SkPixmap pixmap;
511 return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted); 588 pixmap.reset(dti->fData.fInfo, dti->fData.fMipMapLevelData[0].fPixelData ,
589 dti->fData.fMipMapLevelData[0].fRowBytes, colorTable.get()) ;
590 return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
591 } else {
592 SkAutoTDeleteArray<GrMipLevel> texels(new GrMipLevel[mipLevelCount]);
593 for (int i = 0; i < mipLevelCount; i++) {
594 texels[i].fPixels = dti->fData.fMipMapLevelData[i].fPixelData;
595 texels[i].fRowBytes = dti->fData.fMipMapLevelData[i].fRowBytes;
596 }
597
598 return SkImage::MakeTextureFromMipMap(context, dti->fData.fInfo, texels. get(),
599 mipLevelCount, SkBudgeted::kYes,
600 dti->fGammaTreatment);
601 }
512 } 602 }
513 603
514 //////////////////////////////////////////////////////////////////////////////// /////////////////// 604 //////////////////////////////////////////////////////////////////////////////// ///////////////////
515 605
516 GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) { 606 GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) {
517 GrContext* ctx = src->getContext(); 607 GrContext* ctx = src->getContext();
518 608
519 GrSurfaceDesc desc = src->desc(); 609 GrSurfaceDesc desc = src->desc();
520 GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, nullp tr, 0); 610 GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, nullp tr, 0);
521 if (!dst) { 611 if (!dst) {
522 return nullptr; 612 return nullptr;
523 } 613 }
524 614
525 const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight); 615 const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight);
526 const SkIPoint dstP = SkIPoint::Make(0, 0); 616 const SkIPoint dstP = SkIPoint::Make(0, 0);
527 ctx->copySurface(dst, src, srcR, dstP); 617 ctx->copySurface(dst, src, srcR, dstP);
528 ctx->flushSurfaceWrites(dst); 618 ctx->flushSurfaceWrites(dst);
529 return dst; 619 return dst;
530 } 620 }
531 621
532 sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info, 622 sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info,
533 const GrMipLevel* texels, int mipL evelCount, 623 const GrMipLevel* texels, int mipL evelCount,
534 SkBudgeted budgeted) { 624 SkBudgeted budgeted,
625 SkSourceGammaTreatment gammaTreatm ent) {
535 if (!ctx) { 626 if (!ctx) {
536 return nullptr; 627 return nullptr;
537 } 628 }
538 SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, m ipLevelCount)); 629 SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, m ipLevelCount));
539 if (!texture) { 630 if (!texture) {
540 return nullptr; 631 return nullptr;
541 } 632 }
633 texture->texturePriv().setGammaTreatment(gammaTreatment);
542 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNew ImageUniqueID, 634 return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNew ImageUniqueID,
543 info.alphaType(), texture, budgeted); 635 info.alphaType(), texture, budgeted);
544 } 636 }
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