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 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 surface->surfacePriv().hasPendingIO()) { | 340 surface->surfacePriv().hasPendingIO()) { |
341 this->flush(); | 341 this->flush(); |
342 } | 342 } |
343 return fGpu->writeTexturePixels(texture, left, top, width, height, | 343 return fGpu->writeTexturePixels(texture, left, top, width, height, |
344 srcConfig, buffer, rowBytes); | 344 srcConfig, buffer, rowBytes); |
345 // Don't need to check kFlushWrites_PixelOp here, we just did a dire
ct write so the | 345 // Don't need to check kFlushWrites_PixelOp here, we just did a dire
ct write so the |
346 // upload is already flushed. | 346 // upload is already flushed. |
347 } | 347 } |
348 } | 348 } |
349 | 349 |
| 350 // Trim the params here so that if we wind up making a temporary surface it
can be as small as |
| 351 // necessary. |
| 352 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height
(), |
| 353 GrBytesPerPixel(srcConfig), &left
, &top, &width, |
| 354 &height, &buffer, &rowBytes)) { |
| 355 return false; |
| 356 } |
| 357 |
350 // If we didn't do a direct texture write then we upload the pixels to a tex
ture and draw. | 358 // If we didn't do a direct texture write then we upload the pixels to a tex
ture and draw. |
351 GrRenderTarget* renderTarget = surface->asRenderTarget(); | 359 GrRenderTarget* renderTarget = surface->asRenderTarget(); |
352 if (!renderTarget) { | 360 if (!renderTarget) { |
353 return false; | 361 return false; |
354 } | 362 } |
355 | 363 |
356 // We ignore the preferred config unless it is a R/B swap of the src config.
In that case | 364 // We ignore the preferred config unless it is a R/B swap of the src config.
In that case |
357 // we will upload the original src data to a scratch texture but we will spo
of it as the swapped | 365 // we will upload the original src data to a scratch texture but we will spo
of it as the swapped |
358 // config. This scratch will then have R and B swapped. We correct for this
by swapping again | 366 // config. This scratch will then have R and B swapped. We correct for this
by swapping again |
359 // when drawing the scratch to the dst using a conversion effect. | 367 // when drawing the scratch to the dst using a conversion effect. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 // toggles between RGBA and BGRA | 453 // toggles between RGBA and BGRA |
446 static SkColorType toggle_colortype32(SkColorType ct) { | 454 static SkColorType toggle_colortype32(SkColorType ct) { |
447 if (kRGBA_8888_SkColorType == ct) { | 455 if (kRGBA_8888_SkColorType == ct) { |
448 return kBGRA_8888_SkColorType; | 456 return kBGRA_8888_SkColorType; |
449 } else { | 457 } else { |
450 SkASSERT(kBGRA_8888_SkColorType == ct); | 458 SkASSERT(kBGRA_8888_SkColorType == ct); |
451 return kRGBA_8888_SkColorType; | 459 return kRGBA_8888_SkColorType; |
452 } | 460 } |
453 } | 461 } |
454 | 462 |
455 bool GrContext::readRenderTargetPixels(GrRenderTarget* target, | 463 bool GrContext::readSurfacePixels(GrSurface* src, |
456 int left, int top, int width, int height, | 464 int left, int top, int width, int height, |
457 GrPixelConfig dstConfig, void* buffer, si
ze_t rowBytes, | 465 GrPixelConfig dstConfig, void* buffer, size_t
rowBytes, |
458 uint32_t flags) { | 466 uint32_t flags) { |
459 RETURN_FALSE_IF_ABANDONED | 467 RETURN_FALSE_IF_ABANDONED |
460 ASSERT_OWNED_RESOURCE(target); | 468 ASSERT_OWNED_RESOURCE(src); |
461 SkASSERT(target); | 469 SkASSERT(src); |
462 | 470 |
463 if (!(kDontFlush_PixelOpsFlag & flags) && target->surfacePriv().hasPendingWr
ite()) { | 471 // 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. |
| 473 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(), |
| 474 GrBytesPerPixel(dstConfig), &left, |
| 475 &top, &width, &height, &buffer, &r
owBytes)) { |
| 476 return false; |
| 477 } |
| 478 |
| 479 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite
()) { |
464 this->flush(); | 480 this->flush(); |
465 } | 481 } |
466 | 482 |
467 // Determine which conversions have to be applied: flipY, swapRAnd, and/or u
npremul. | 483 // Determine which conversions have to be applied: flipY, swapRAnd, and/or u
npremul. |
468 | 484 |
469 // If fGpu->readPixels would incur a y-flip cost then we will read the pixel
s upside down. We'll | |
470 // either do the flipY by drawing into a scratch with a matrix or on the cpu
after the read. | |
471 bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top, | |
472 width, height, dstConfig, | |
473 rowBytes); | |
474 // We ignore the preferred config if it is different than our config unless
it is an R/B swap. | 485 // We ignore the preferred config if it is different than our config unless
it is an R/B swap. |
475 // In that case we'll perform an R and B swap while drawing to a scratch tex
ture of the swapped | 486 // In that case we'll perform an R and B swap while drawing to a scratch tex
ture of the swapped |
476 // config. Then we will call readPixels on the scratch with the swapped conf
ig. The swaps during | 487 // config. Then we will call readPixels on the scratch with the swapped conf
ig. The swaps during |
477 // the draw cancels out the fact that we call readPixels with a config that
is R/B swapped from | 488 // the draw cancels out the fact that we call readPixels with a config that
is R/B swapped from |
478 // dstConfig. | 489 // dstConfig. |
479 GrPixelConfig readConfig = dstConfig; | 490 GrPixelConfig readConfig = dstConfig; |
480 bool swapRAndB = false; | 491 bool swapRAndB = false; |
481 if (GrPixelConfigSwapRAndB(dstConfig) == | 492 if (GrPixelConfigSwapRAndB(dstConfig) == |
482 fGpu->preferredReadPixelsConfig(dstConfig, target->config())) { | 493 fGpu->preferredReadPixelsConfig(dstConfig, src->config())) { |
483 readConfig = GrPixelConfigSwapRAndB(readConfig); | 494 readConfig = GrPixelConfigSwapRAndB(readConfig); |
484 swapRAndB = true; | 495 swapRAndB = true; |
485 } | 496 } |
486 | 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 |
487 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); | 509 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); |
488 | |
489 if (unpremul && !GrPixelConfigIs8888(dstConfig)) { | 510 if (unpremul && !GrPixelConfigIs8888(dstConfig)) { |
490 // The unpremul flag is only allowed for these two configs. | 511 // The unpremul flag is only allowed for these two configs. |
491 return false; | 512 return false; |
492 } | 513 } |
493 | 514 |
494 SkAutoTUnref<GrTexture> tempTexture; | 515 SkAutoTUnref<GrTexture> tempTexture; |
495 | 516 |
496 // If the src is a texture and we would have to do conversions after read pi
xels, we instead | 517 // If the src is a texture and we would have to do conversions after read pi
xels, we instead |
497 // do the conversions by drawing the src to a scratch texture. If we handle
any of the | 518 // do the conversions by drawing the src to a scratch texture. If we handle
any of the |
498 // conversions in the draw we set the corresponding bool to false so that we
don't reapply it | 519 // conversions in the draw we set the corresponding bool to false so that we
don't reapply it |
499 // on the read back pixels. | 520 // on the read back pixels. We also do an intermediate draw if the src is no
t a render target as |
500 GrTexture* src = target->asTexture(); | 521 // GrGpu currently supports reading from render targets but not textures. |
501 if (src && (swapRAndB || unpremul || flipY)) { | 522 GrTexture* srcAsTex = src->asTexture(); |
| 523 GrRenderTarget* rtToRead = srcAsRT; |
| 524 if (srcAsTex && (swapRAndB || unpremul || flipY || !srcAsRT)) { |
502 // Make the scratch a render so we can read its pixels. | 525 // Make the scratch a render so we can read its pixels. |
503 GrSurfaceDesc desc; | 526 GrSurfaceDesc desc; |
504 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 527 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
505 desc.fWidth = width; | 528 desc.fWidth = width; |
506 desc.fHeight = height; | 529 desc.fHeight = height; |
507 desc.fConfig = readConfig; | 530 desc.fConfig = readConfig; |
508 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | 531 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
509 | 532 |
510 // When a full read back is faster than a partial we could always make t
he scratch exactly | 533 // When a full read back is faster than a partial we could always make t
he scratch exactly |
511 // match the passed rect. However, if we see many different size rectang
les we will trash | 534 // match the passed rect. However, if we see many different size rectang
les we will trash |
512 // our texture cache and pay the cost of creating and destroying many te
xtures. So, we only | 535 // our texture cache and pay the cost of creating and destroying many te
xtures. So, we only |
513 // request an exact match when the caller is reading an entire RT. | 536 // request an exact match when the caller is reading an entire RT. |
514 GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_Sc
ratchTexMatch; | 537 GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_Sc
ratchTexMatch; |
515 if (0 == left && | 538 if (0 == left && |
516 0 == top && | 539 0 == top && |
517 target->width() == width && | 540 src->width() == width && |
518 target->height() == height && | 541 src->height() == height && |
519 fGpu->fullReadPixelsIsFasterThanPartial()) { | 542 fGpu->fullReadPixelsIsFasterThanPartial()) { |
520 match = GrTextureProvider::kExact_ScratchTexMatch; | 543 match = GrTextureProvider::kExact_ScratchTexMatch; |
521 } | 544 } |
522 tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match
)); | 545 tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match
)); |
523 if (tempTexture) { | 546 if (tempTexture) { |
524 // compute a matrix to perform the draw | 547 // compute a matrix to perform the draw |
525 SkMatrix textureMatrix; | 548 SkMatrix textureMatrix; |
526 textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top); | 549 textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top); |
527 textureMatrix.postIDiv(src->width(), src->height()); | 550 textureMatrix.postIDiv(src->width(), src->height()); |
528 | 551 |
529 GrPaint paint; | 552 GrPaint paint; |
530 SkAutoTUnref<const GrFragmentProcessor> fp; | 553 SkAutoTUnref<const GrFragmentProcessor> fp; |
531 if (unpremul) { | 554 if (unpremul) { |
532 fp.reset(this->createPMToUPMEffect(paint.getProcessorDataManager
(), src, swapRAndB, | 555 fp.reset(this->createPMToUPMEffect(paint.getProcessorDataManager
(), srcAsTex, |
533 textureMatrix)); | 556 swapRAndB, textureMatrix)); |
534 if (fp) { | 557 if (fp) { |
535 unpremul = false; // we no longer need to do this on CPU aft
er the read back. | 558 unpremul = false; // we no longer need to do this on CPU aft
er the read back. |
536 } | 559 } |
537 } | 560 } |
538 // If we failed to create a PM->UPM effect and have no other convers
ions to perform then | 561 // If we failed to create a PM->UPM effect and have no other convers
ions to perform then |
539 // there is no longer any point to using the scratch. | 562 // there is no longer any point to using the scratch. |
540 if (fp || flipY || swapRAndB) { | 563 if (fp || flipY || swapRAndB || !srcAsRT) { |
541 if (!fp) { | 564 if (!fp) { |
542 fp.reset(GrConfigConversionEffect::Create(paint.getProcessor
DataManager(), | 565 fp.reset(GrConfigConversionEffect::Create(paint.getProcessor
DataManager(), |
543 src, swapRAndB, GrConfigConversionEffect::kNone_PMCo
nversion, | 566 srcAsTex, swapRAndB, GrConfigConversionEffect::kNone
_PMConversion, |
544 textureMatrix)); | 567 textureMatrix)); |
545 } | 568 } |
546 swapRAndB = false; // we will handle the swap in the draw. | 569 swapRAndB = false; // we will handle the swap in the draw. |
547 | 570 |
548 // We protect the existing geometry here since it may not be | 571 // We protect the existing geometry here since it may not be |
549 // clear to the caller that a draw operation (i.e., drawSimpleRe
ct) | 572 // clear to the caller that a draw operation (i.e., drawSimpleRe
ct) |
550 // can be invoked in this method | 573 // can be invoked in this method |
551 { | 574 { |
552 GrDrawContext* drawContext = this->drawContext(); | 575 GrDrawContext* drawContext = this->drawContext(); |
553 if (!drawContext) { | 576 if (!drawContext) { |
554 return false; | 577 return false; |
555 } | 578 } |
556 | 579 |
557 paint.addColorProcessor(fp); | 580 paint.addColorProcessor(fp); |
558 | 581 |
559 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToSc
alar(height)); | 582 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToSc
alar(height)); |
560 | 583 |
561 drawContext->drawRect(tempTexture->asRenderTarget(), GrClip:
:WideOpen(), paint, | 584 drawContext->drawRect(tempTexture->asRenderTarget(), GrClip:
:WideOpen(), paint, |
562 SkMatrix::I(), rect, NULL);
| 585 SkMatrix::I(), rect, NULL);
|
563 | 586 |
564 // we want to read back from the scratch's origin | 587 // we want to read back from the scratch's origin |
565 left = 0; | 588 left = 0; |
566 top = 0; | 589 top = 0; |
567 target = tempTexture->asRenderTarget(); | 590 rtToRead = tempTexture->asRenderTarget(); |
568 } | 591 } |
569 this->flushSurfaceWrites(target); | 592 this->flushSurfaceWrites(tempTexture); |
570 } | 593 } |
571 } | 594 } |
572 } | 595 } |
573 | 596 |
574 if (!fGpu->readPixels(target, | 597 if (!rtToRead || |
575 left, top, width, height, | 598 !fGpu->readPixels(rtToRead, left, top, width, height, readConfig, buffer
, rowBytes)) { |
576 readConfig, buffer, rowBytes)) { | |
577 return false; | 599 return false; |
578 } | 600 } |
579 // Perform any conversions we weren't able to perform using a scratch textur
e. | 601 // Perform any conversions we weren't able to perform using a scratch textur
e. |
580 if (unpremul || swapRAndB) { | 602 if (unpremul || swapRAndB) { |
581 SkDstPixelInfo dstPI; | 603 SkDstPixelInfo dstPI; |
582 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NUL
L)) { | 604 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NUL
L)) { |
583 return false; | 605 return false; |
584 } | 606 } |
585 dstPI.fAlphaType = kUnpremul_SkAlphaType; | 607 dstPI.fAlphaType = kUnpremul_SkAlphaType; |
586 dstPI.fPixels = buffer; | 608 dstPI.fPixels = buffer; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 ////////////////////////////////////////////////////////////////////////////// | 785 ////////////////////////////////////////////////////////////////////////////// |
764 | 786 |
765 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { | 787 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { |
766 fGpu->addGpuTraceMarker(marker); | 788 fGpu->addGpuTraceMarker(marker); |
767 } | 789 } |
768 | 790 |
769 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { | 791 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { |
770 fGpu->removeGpuTraceMarker(marker); | 792 fGpu->removeGpuTraceMarker(marker); |
771 } | 793 } |
772 | 794 |
OLD | NEW |