| 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 |