OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |