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

Side by Side Diff: src/gpu/GrContext.cpp

Issue 1255483005: Attempt to somewhat simplify GrContext::readSurfacePixels interaction with GrGpu. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments Created 5 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
« no previous file with comments | « no previous file | src/gpu/GrGpu.h » ('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 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "GrContext.h" 9 #include "GrContext.h"
10 10
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 443
444 drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL); 444 drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
445 445
446 if (kFlushWrites_PixelOp & pixelOpsFlags) { 446 if (kFlushWrites_PixelOp & pixelOpsFlags) {
447 this->flushSurfaceWrites(surface); 447 this->flushSurfaceWrites(surface);
448 } 448 }
449 449
450 return true; 450 return true;
451 } 451 }
452 452
453 // toggles between RGBA and BGRA
454 static SkColorType toggle_colortype32(SkColorType ct) {
455 if (kRGBA_8888_SkColorType == ct) {
456 return kBGRA_8888_SkColorType;
457 } else {
458 SkASSERT(kBGRA_8888_SkColorType == ct);
459 return kRGBA_8888_SkColorType;
460 }
461 }
462
463 bool GrContext::readSurfacePixels(GrSurface* src, 453 bool GrContext::readSurfacePixels(GrSurface* src,
464 int left, int top, int width, int height, 454 int left, int top, int width, int height,
465 GrPixelConfig dstConfig, void* buffer, size_t rowBytes, 455 GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
466 uint32_t flags) { 456 uint32_t flags) {
467 RETURN_FALSE_IF_ABANDONED 457 RETURN_FALSE_IF_ABANDONED
468 ASSERT_OWNED_RESOURCE(src); 458 ASSERT_OWNED_RESOURCE(src);
469 SkASSERT(src); 459 SkASSERT(src);
470 460
471 // Adjust the params so that if we wind up using an intermediate surface we' ve already done 461 // Adjust the params so that if we wind up using an intermediate surface we' ve already done
472 // all the trimming and the temporary can be the min size required. 462 // all the trimming and the temporary can be the min size required.
473 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(), 463 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
474 GrBytesPerPixel(dstConfig), &left, 464 GrBytesPerPixel(dstConfig), &left,
475 &top, &width, &height, &buffer, &r owBytes)) { 465 &top, &width, &height, &buffer, &r owBytes)) {
476 return false; 466 return false;
477 } 467 }
478 468
479 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite ()) { 469 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite ()) {
480 this->flush(); 470 this->flush();
481 } 471 }
482 472
483 // Determine which conversions have to be applied: flipY, swapRAnd, and/or u npremul.
484
485 // We ignore the preferred config if it is different than our config unless it is an R/B swap.
486 // In that case we'll perform an R and B swap while drawing to a scratch tex ture of the swapped
487 // config. Then we will call readPixels on the scratch with the swapped conf ig. The swaps during
488 // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
489 // dstConfig.
490 GrPixelConfig readConfig = dstConfig;
491 bool swapRAndB = false;
492 if (GrPixelConfigSwapRAndB(dstConfig) ==
493 fGpu->preferredReadPixelsConfig(dstConfig, src->config())) {
494 readConfig = GrPixelConfigSwapRAndB(readConfig);
495 swapRAndB = true;
496 }
497
498 bool flipY = false;
499 GrRenderTarget* srcAsRT = src->asRenderTarget();
500 if (srcAsRT) {
501 // If fGpu->readPixels would incur a y-flip cost then we will read the p ixels upside down.
502 // We'll either do the flipY by drawing into a scratch with a matrix or on the cpu after the
503 // read.
504 flipY = fGpu->readPixelsWillPayForYFlip(srcAsRT, left, top,
505 width, height, dstConfig,
506 rowBytes);
507 }
508
509 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); 473 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
510 if (unpremul && !GrPixelConfigIs8888(dstConfig)) { 474 if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
511 // The unpremul flag is only allowed for these two configs. 475 // The unpremul flag is only allowed for 8888 configs.
512 return false; 476 return false;
513 } 477 }
514 478
515 SkAutoTUnref<GrTexture> tempTexture; 479 GrGpu::DrawPreference drawPreference = unpremul ? GrGpu::kCallerPrefersDraw_ DrawPreference :
480 GrGpu::kNoDraw_DrawPrefere nce;
481 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
482 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawP reference,
483 &tempDrawInfo)) {
484 return false;
485 }
516 486
517 // If the src is a texture and we would have to do conversions after read pi xels, we instead 487 GrRenderTarget* rtToRead = src->asRenderTarget();
518 // do the conversions by drawing the src to a scratch texture. If we handle any of the 488 bool didTempDraw = false;
519 // conversions in the draw we set the corresponding bool to false so that we don't reapply it 489 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
520 // on the read back pixels. We also do an intermediate draw if the src is no t a render target as
521 // GrGpu currently supports reading from render targets but not textures.
522 GrTexture* srcAsTex = src->asTexture();
523 GrRenderTarget* rtToRead = srcAsRT;
524 if (srcAsTex && (swapRAndB || unpremul || flipY || !srcAsRT)) {
525 // Make the scratch a render so we can read its pixels.
526 GrSurfaceDesc desc;
527 desc.fFlags = kRenderTarget_GrSurfaceFlag;
528 desc.fWidth = width;
529 desc.fHeight = height;
530 desc.fConfig = readConfig;
531 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
532
533 // When a full read back is faster than a partial we could always make t he scratch exactly
534 // match the passed rect. However, if we see many different size rectang les we will trash
535 // our texture cache and pay the cost of creating and destroying many te xtures. So, we only
536 // request an exact match when the caller is reading an entire RT.
537 GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_Sc ratchTexMatch; 490 GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_Sc ratchTexMatch;
538 if (0 == left && 491 if (tempDrawInfo.fUseExactScratch) {
539 0 == top && 492 // We only respect this when the entire src is being read. Otherwise we can trigger too
540 src->width() == width && 493 // many odd ball texture sizes and trash the cache.
541 src->height() == height && 494 if (width == src->width() && height == src->height()) {
542 fGpu->fullReadPixelsIsFasterThanPartial()) { 495 match = GrTextureProvider::kExact_ScratchTexMatch;
543 match = GrTextureProvider::kExact_ScratchTexMatch; 496 }
544 } 497 }
545 tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match )); 498 SkAutoTUnref<GrTexture> temp;
546 if (tempTexture) { 499 temp.reset(this->textureProvider()->refScratchTexture(tempDrawInfo.fTemp SurfaceDesc, match));
547 // compute a matrix to perform the draw 500 if (temp) {
548 SkMatrix textureMatrix; 501 SkMatrix textureMatrix;
549 textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top); 502 textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
550 textureMatrix.postIDiv(src->width(), src->height()); 503 textureMatrix.postIDiv(src->width(), src->height());
551
552 GrPaint paint; 504 GrPaint paint;
553 SkAutoTUnref<const GrFragmentProcessor> fp; 505 SkAutoTUnref<const GrFragmentProcessor> fp;
554 if (unpremul) { 506 if (unpremul) {
555 fp.reset(this->createPMToUPMEffect(paint.getProcessorDataManager (), srcAsTex, 507 fp.reset(this->createPMToUPMEffect(
556 swapRAndB, textureMatrix)); 508 paint.getProcessorDataManager(), src->asTexture(), tempDrawI nfo.fSwapRAndB,
509 textureMatrix));
557 if (fp) { 510 if (fp) {
558 unpremul = false; // we no longer need to do this on CPU aft er the read back. 511 unpremul = false; // we no longer need to do this on CPU aft er the read back.
512 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPrefe rence) {
513 // We only wanted to do the draw in order to perform the unp remul so don't
514 // bother.
515 temp.reset(NULL);
559 } 516 }
560 } 517 }
561 // If we failed to create a PM->UPM effect and have no other convers ions to perform then 518 if (!fp && temp) {
562 // there is no longer any point to using the scratch. 519 fp.reset(GrConfigConversionEffect::Create(
563 if (fp || flipY || swapRAndB || !srcAsRT) { 520 paint.getProcessorDataManager(), src->asTexture(), tempDrawI nfo.fSwapRAndB,
564 if (!fp) { 521 GrConfigConversionEffect::kNone_PMConversion, textureMatrix) );
565 fp.reset(GrConfigConversionEffect::Create(paint.getProcessor DataManager(), 522 }
566 srcAsTex, swapRAndB, GrConfigConversionEffect::kNone _PMConversion, 523 if (fp) {
567 textureMatrix)); 524 paint.addColorProcessor(fp);
568 } 525 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar (height));
569 swapRAndB = false; // we will handle the swap in the draw. 526 GrDrawContext* drawContext = this->drawContext();
570 527 drawContext->drawRect(temp->asRenderTarget(), GrClip::WideOpen() , paint,
571 // We protect the existing geometry here since it may not be 528 SkMatrix::I(), rect, NULL);
572 // clear to the caller that a draw operation (i.e., drawSimpleRe ct) 529 rtToRead = temp->asRenderTarget();
573 // can be invoked in this method 530 left = 0;
574 { 531 top = 0;
575 GrDrawContext* drawContext = this->drawContext(); 532 didTempDraw = true;
576 if (!drawContext) {
577 return false;
578 }
579
580 paint.addColorProcessor(fp);
581
582 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToSc alar(height));
583
584 drawContext->drawRect(tempTexture->asRenderTarget(), GrClip: :WideOpen(), paint,
585 SkMatrix::I(), rect, NULL);
586
587 // we want to read back from the scratch's origin
588 left = 0;
589 top = 0;
590 rtToRead = tempTexture->asRenderTarget();
591 }
592 this->flushSurfaceWrites(tempTexture);
593 } 533 }
594 } 534 }
595 } 535 }
596 536
597 if (!rtToRead || 537 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
598 !fGpu->readPixels(rtToRead, left, top, width, height, readConfig, buffer , rowBytes)) {
599 return false; 538 return false;
600 } 539 }
601 // Perform any conversions we weren't able to perform using a scratch textur e. 540 GrPixelConfig configToRead = dstConfig;
602 if (unpremul || swapRAndB) { 541 if (didTempDraw) {
542 this->flushSurfaceWrites(rtToRead);
543 // We swapped R and B while doing the temp draw. Swap back on the read.
544 if (tempDrawInfo.fSwapRAndB) {
545 configToRead = GrPixelConfigSwapRAndB(dstConfig);
546 }
547 }
548 if (!fGpu->readPixels(rtToRead, left, top, width, height, configToRead, buff er, rowBytes)) {
549 return false;
550 }
551
552 // Perform umpremul conversion if we weren't able to perform it as a draw.
553 if (unpremul) {
603 SkDstPixelInfo dstPI; 554 SkDstPixelInfo dstPI;
604 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NUL L)) { 555 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NUL L)) {
605 return false; 556 return false;
606 } 557 }
607 dstPI.fAlphaType = kUnpremul_SkAlphaType; 558 dstPI.fAlphaType = kUnpremul_SkAlphaType;
608 dstPI.fPixels = buffer; 559 dstPI.fPixels = buffer;
609 dstPI.fRowBytes = rowBytes; 560 dstPI.fRowBytes = rowBytes;
610 561
611 SkSrcPixelInfo srcPI; 562 SkSrcPixelInfo srcPI;
612 srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : ds tPI.fColorType; 563 srcPI.fColorType = dstPI.fColorType;
613 srcPI.fAlphaType = kPremul_SkAlphaType; 564 srcPI.fAlphaType = kPremul_SkAlphaType;
614 srcPI.fPixels = buffer; 565 srcPI.fPixels = buffer;
615 srcPI.fRowBytes = rowBytes; 566 srcPI.fRowBytes = rowBytes;
616 567
617 return srcPI.convertPixelsTo(&dstPI, width, height); 568 return srcPI.convertPixelsTo(&dstPI, width, height);
618 } 569 }
619 return true; 570 return true;
620 } 571 }
621 572
622 void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) { 573 void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 ////////////////////////////////////////////////////////////////////////////// 736 //////////////////////////////////////////////////////////////////////////////
786 737
787 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 738 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
788 fGpu->addGpuTraceMarker(marker); 739 fGpu->addGpuTraceMarker(marker);
789 } 740 }
790 741
791 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 742 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
792 fGpu->removeGpuTraceMarker(marker); 743 fGpu->removeGpuTraceMarker(marker);
793 } 744 }
794 745
OLDNEW
« no previous file with comments | « no previous file | src/gpu/GrGpu.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698