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 | 9 |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
(...skipping 1356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1367 return false; | 1367 return false; |
1368 } | 1368 } |
1369 } | 1369 } |
1370 | 1370 |
1371 if (!(kDontFlush_PixelOpsFlag & flags) && texture->surfacePriv().hasPendingI
O()) { | 1371 if (!(kDontFlush_PixelOpsFlag & flags) && texture->surfacePriv().hasPendingI
O()) { |
1372 this->flush(); | 1372 this->flush(); |
1373 } | 1373 } |
1374 | 1374 |
1375 return fGpu->writeTexturePixels(texture, left, top, width, height, | 1375 return fGpu->writeTexturePixels(texture, left, top, width, height, |
1376 config, buffer, rowBytes); | 1376 config, buffer, rowBytes); |
| 1377 |
| 1378 // No need to check the kFlushWrites flag here since we issued the write dir
ectly to fGpu. |
1377 } | 1379 } |
1378 | 1380 |
1379 bool GrContext::readTexturePixels(GrTexture* texture, | 1381 bool GrContext::readTexturePixels(GrTexture* texture, |
1380 int left, int top, int width, int height, | 1382 int left, int top, int width, int height, |
1381 GrPixelConfig config, void* buffer, size_t row
Bytes, | 1383 GrPixelConfig config, void* buffer, size_t row
Bytes, |
1382 uint32_t flags) { | 1384 uint32_t flags) { |
1383 ASSERT_OWNED_RESOURCE(texture); | 1385 ASSERT_OWNED_RESOURCE(texture); |
1384 | 1386 |
1385 GrRenderTarget* target = texture->asRenderTarget(); | 1387 GrRenderTarget* target = texture->asRenderTarget(); |
1386 if (target) { | 1388 if (target) { |
1387 return this->readRenderTargetPixels(target, | 1389 return this->readRenderTargetPixels(target, |
1388 left, top, width, height, | 1390 left, top, width, height, |
1389 config, buffer, rowBytes, | 1391 config, buffer, rowBytes, |
1390 flags); | 1392 flags); |
1391 } else { | 1393 } else { |
1392 // TODO: make this more efficient for cases where we're reading the enti
re | 1394 // TODO: make this more efficient for cases where we're reading the enti
re |
1393 // texture, i.e., use GetTexImage() instead | 1395 // texture, i.e., use GetTexImage() instead |
1394 | 1396 |
1395 // create scratch rendertarget and read from that | 1397 // create scratch rendertarget and read from that |
1396 GrAutoScratchTexture ast; | 1398 GrAutoScratchTexture ast; |
1397 GrTextureDesc desc; | 1399 GrTextureDesc desc; |
1398 desc.fFlags = kRenderTarget_GrTextureFlagBit; | 1400 desc.fFlags = kRenderTarget_GrTextureFlagBit; |
1399 desc.fWidth = width; | 1401 desc.fWidth = width; |
1400 desc.fHeight = height; | 1402 desc.fHeight = height; |
1401 desc.fConfig = config; | 1403 desc.fConfig = config; |
1402 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | 1404 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
1403 ast.set(this, desc, kExact_ScratchTexMatch); | 1405 ast.set(this, desc, kExact_ScratchTexMatch); |
1404 GrTexture* dst = ast.texture(); | 1406 GrTexture* dst = ast.texture(); |
1405 if (dst && (target = dst->asRenderTarget())) { | 1407 if (dst && (target = dst->asRenderTarget())) { |
1406 this->copyTexture(texture, target, NULL); | 1408 this->copySurface(target, texture, SkIRect::MakeXYWH(top, left, widt
h, height), |
| 1409 SkIPoint::Make(0,0)); |
1407 return this->readRenderTargetPixels(target, | 1410 return this->readRenderTargetPixels(target, |
1408 left, top, width, height, | 1411 left, top, width, height, |
1409 config, buffer, rowBytes, | 1412 config, buffer, rowBytes, |
1410 flags); | 1413 flags); |
1411 } | 1414 } |
1412 | 1415 |
1413 return false; | 1416 return false; |
1414 } | 1417 } |
1415 } | 1418 } |
1416 | 1419 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1584 ASSERT_OWNED_RESOURCE(renderTarget); | 1587 ASSERT_OWNED_RESOURCE(renderTarget); |
1585 AutoRestoreEffects are; | 1588 AutoRestoreEffects are; |
1586 AutoCheckFlush acf(this); | 1589 AutoCheckFlush acf(this); |
1587 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf); | 1590 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf); |
1588 if (NULL == target) { | 1591 if (NULL == target) { |
1589 return; | 1592 return; |
1590 } | 1593 } |
1591 target->discard(renderTarget); | 1594 target->discard(renderTarget); |
1592 } | 1595 } |
1593 | 1596 |
1594 void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint*
topLeft) { | 1597 void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe
ct, |
| 1598 const SkIPoint& dstPoint, uint32_t pixelOpsFlags) { |
1595 if (NULL == src || NULL == dst) { | 1599 if (NULL == src || NULL == dst) { |
1596 return; | 1600 return; |
1597 } | 1601 } |
1598 ASSERT_OWNED_RESOURCE(src); | 1602 ASSERT_OWNED_RESOURCE(src); |
1599 ASSERT_OWNED_RESOURCE(dst); | 1603 ASSERT_OWNED_RESOURCE(dst); |
1600 | 1604 |
1601 SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height()); | 1605 // Since we're going to the draw target and not GPU, no need to check kNoFlu
sh |
1602 if (topLeft) { | 1606 // here. |
1603 srcRect.offset(*topLeft); | |
1604 } | |
1605 SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height()); | |
1606 if (!srcRect.intersect(srcBounds)) { | |
1607 return; | |
1608 } | |
1609 | 1607 |
1610 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL); | 1608 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL); |
1611 if (NULL == target) { | 1609 if (NULL == target) { |
1612 return; | 1610 return; |
1613 } | 1611 } |
1614 SkIPoint dstPoint; | |
1615 dstPoint.setZero(); | |
1616 target->copySurface(dst, src, srcRect, dstPoint); | 1612 target->copySurface(dst, src, srcRect, dstPoint); |
| 1613 |
| 1614 if (kFlushWrites_PixelOp & pixelOpsFlags) { |
| 1615 this->flush(); |
| 1616 } |
1617 } | 1617 } |
1618 | 1618 |
1619 bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget, | 1619 bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget, |
1620 int left, int top, int width, int height
, | 1620 int left, int top, int width, int height
, |
1621 GrPixelConfig srcConfig, | 1621 GrPixelConfig srcConfig, |
1622 const void* buffer, | 1622 const void* buffer, |
1623 size_t rowBytes, | 1623 size_t rowBytes, |
1624 uint32_t flags) { | 1624 uint32_t pixelOpsFlags) { |
1625 ASSERT_OWNED_RESOURCE(renderTarget); | 1625 ASSERT_OWNED_RESOURCE(renderTarget); |
1626 | 1626 |
1627 if (NULL == renderTarget) { | 1627 if (NULL == renderTarget) { |
1628 renderTarget = fRenderTarget.get(); | 1628 renderTarget = fRenderTarget.get(); |
1629 if (NULL == renderTarget) { | 1629 if (NULL == renderTarget) { |
1630 return false; | 1630 return false; |
1631 } | 1631 } |
1632 } | 1632 } |
1633 | 1633 |
1634 // TODO: when underlying api has a direct way to do this we should use it (e
.g. glDrawPixels on | 1634 // TODO: when underlying api has a direct way to do this we should use it (e
.g. glDrawPixels on |
1635 // desktop GL). | 1635 // desktop GL). |
1636 | 1636 |
1637 // We will always call some form of writeTexturePixels and we will pass our
flags on to it. | 1637 // We will always call some form of writeTexturePixels and we will pass our
flags on to it. |
1638 // Thus, we don't perform a flush here since that call will do it (if the kN
oFlush flag isn't | 1638 // Thus, we don't perform a flush here since that call will do it (if the kN
oFlush flag isn't |
1639 // set.) | 1639 // set.) |
1640 | 1640 |
1641 // If the RT is also a texture and we don't have to premultiply then take th
e texture path. | 1641 // If the RT is also a texture and we don't have to premultiply then take th
e texture path. |
1642 // We expect to be at least as fast or faster since it doesn't use an interm
ediate texture as | 1642 // We expect to be at least as fast or faster since it doesn't use an interm
ediate texture as |
1643 // we do below. | 1643 // we do below. |
1644 | 1644 |
1645 #if !defined(SK_BUILD_FOR_MAC) | 1645 #if !defined(SK_BUILD_FOR_MAC) |
1646 // At least some drivers on the Mac get confused when glTexImage2D is called
on a texture | 1646 // At least some drivers on the Mac get confused when glTexImage2D is called
on a texture |
1647 // attached to an FBO. The FBO still sees the old image. TODO: determine wha
t OS versions and/or | 1647 // attached to an FBO. The FBO still sees the old image. TODO: determine wha
t OS versions and/or |
1648 // HW is affected. | 1648 // HW is affected. |
1649 if (renderTarget->asTexture() && !(kUnpremul_PixelOpsFlag & flags) && | 1649 if (renderTarget->asTexture() && !(kUnpremul_PixelOpsFlag & pixelOpsFlags) &
& |
1650 fGpu->canWriteTexturePixels(renderTarget->asTexture(), srcConfig)) { | 1650 fGpu->canWriteTexturePixels(renderTarget->asTexture(), srcConfig)) { |
1651 return this->writeTexturePixels(renderTarget->asTexture(), | 1651 return this->writeTexturePixels(renderTarget->asTexture(), |
1652 left, top, width, height, | 1652 left, top, width, height, |
1653 srcConfig, buffer, rowBytes, flags); | 1653 srcConfig, buffer, rowBytes, pixelOpsFla
gs); |
1654 } | 1654 } |
1655 #endif | 1655 #endif |
1656 | 1656 |
1657 // We ignore the preferred config unless it is a R/B swap of the src config.
In that case | 1657 // We ignore the preferred config unless it is a R/B swap of the src config.
In that case |
1658 // we will upload the original src data to a scratch texture but we will spo
of it as the swapped | 1658 // we will upload the original src data to a scratch texture but we will spo
of it as the swapped |
1659 // config. This scratch will then have R and B swapped. We correct for this
by swapping again | 1659 // config. This scratch will then have R and B swapped. We correct for this
by swapping again |
1660 // when drawing the scratch to the dst using a conversion effect. | 1660 // when drawing the scratch to the dst using a conversion effect. |
1661 bool swapRAndB = false; | 1661 bool swapRAndB = false; |
1662 GrPixelConfig writeConfig = srcConfig; | 1662 GrPixelConfig writeConfig = srcConfig; |
1663 if (GrPixelConfigSwapRAndB(srcConfig) == | 1663 if (GrPixelConfigSwapRAndB(srcConfig) == |
(...skipping 12 matching lines...) Expand all Loading... |
1676 return false; | 1676 return false; |
1677 } | 1677 } |
1678 | 1678 |
1679 SkAutoTUnref<const GrFragmentProcessor> fp; | 1679 SkAutoTUnref<const GrFragmentProcessor> fp; |
1680 SkMatrix textureMatrix; | 1680 SkMatrix textureMatrix; |
1681 textureMatrix.setIDiv(texture->width(), texture->height()); | 1681 textureMatrix.setIDiv(texture->width(), texture->height()); |
1682 | 1682 |
1683 // allocate a tmp buffer and sw convert the pixels to premul | 1683 // allocate a tmp buffer and sw convert the pixels to premul |
1684 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); | 1684 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); |
1685 | 1685 |
1686 if (kUnpremul_PixelOpsFlag & flags) { | 1686 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { |
1687 if (!GrPixelConfigIs8888(srcConfig)) { | 1687 if (!GrPixelConfigIs8888(srcConfig)) { |
1688 return false; | 1688 return false; |
1689 } | 1689 } |
1690 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix)); | 1690 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix)); |
1691 // handle the unpremul step on the CPU if we couldn't create an effect t
o do it. | 1691 // handle the unpremul step on the CPU if we couldn't create an effect t
o do it. |
1692 if (NULL == fp) { | 1692 if (NULL == fp) { |
1693 SkSrcPixelInfo srcPI; | 1693 SkSrcPixelInfo srcPI; |
1694 if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) { | 1694 if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) { |
1695 return false; | 1695 return false; |
1696 } | 1696 } |
(...skipping 20 matching lines...) Expand all Loading... |
1717 if (NULL == fp) { | 1717 if (NULL == fp) { |
1718 fp.reset(GrConfigConversionEffect::Create(texture, | 1718 fp.reset(GrConfigConversionEffect::Create(texture, |
1719 swapRAndB, | 1719 swapRAndB, |
1720 GrConfigConversionEffect::kNon
e_PMConversion, | 1720 GrConfigConversionEffect::kNon
e_PMConversion, |
1721 textureMatrix)); | 1721 textureMatrix)); |
1722 } | 1722 } |
1723 | 1723 |
1724 if (!this->writeTexturePixels(texture, | 1724 if (!this->writeTexturePixels(texture, |
1725 0, 0, width, height, | 1725 0, 0, width, height, |
1726 writeConfig, buffer, rowBytes, | 1726 writeConfig, buffer, rowBytes, |
1727 flags & ~kUnpremul_PixelOpsFlag)) { | 1727 pixelOpsFlags & ~kUnpremul_PixelOpsFlag)) { |
1728 return false; | 1728 return false; |
1729 } | 1729 } |
1730 | 1730 |
1731 SkMatrix matrix; | 1731 SkMatrix matrix; |
1732 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); | 1732 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); |
1733 | 1733 |
| 1734 |
1734 // This function can be called in the midst of drawing another object (e.g.,
when uploading a | 1735 // This function can be called in the midst of drawing another object (e.g.,
when uploading a |
1735 // SW-rasterized clip while issuing a draw). So we push the current geometry
state before | 1736 // SW-rasterized clip while issuing a draw). So we push the current geometry
state before |
1736 // drawing a rect to the render target. | 1737 // drawing a rect to the render target. |
1737 GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL
, NULL); | 1738 // The bracket ensures we pop the stack if we wind up flushing below. |
1738 GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::kRese
t_ASRInit, &matrix); | 1739 { |
1739 GrDrawState* drawState = drawTarget->drawState(); | 1740 GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw,
NULL, NULL); |
1740 drawState->addColorProcessor(fp); | 1741 GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::k
Reset_ASRInit, |
1741 drawState->setRenderTarget(renderTarget); | 1742 &matrix); |
1742 drawState->disableState(GrDrawState::kClip_StateBit); | 1743 GrDrawState* drawState = drawTarget->drawState(); |
1743 drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScala
r(height))); | 1744 drawState->addColorProcessor(fp); |
| 1745 drawState->setRenderTarget(renderTarget); |
| 1746 drawState->disableState(GrDrawState::kClip_StateBit); |
| 1747 drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToS
calar(height))); |
| 1748 } |
| 1749 |
| 1750 if (kFlushWrites_PixelOp & pixelOpsFlags) { |
| 1751 this->flush(); |
| 1752 } |
| 1753 |
1744 return true; | 1754 return true; |
1745 } | 1755 } |
| 1756 |
| 1757 void GrContext::flushSurfaceWrites(GrSurface* surface) { |
| 1758 if (surface->surfacePriv().hasPendingWrite()) { |
| 1759 this->flush(); |
| 1760 } |
| 1761 } |
| 1762 |
1746 //////////////////////////////////////////////////////////////////////////////// | 1763 //////////////////////////////////////////////////////////////////////////////// |
1747 | 1764 |
1748 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, | 1765 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, |
1749 BufferedDraw buffered, | 1766 BufferedDraw buffered, |
1750 AutoRestoreEffects* are, | 1767 AutoRestoreEffects* are, |
1751 AutoCheckFlush* acf) { | 1768 AutoCheckFlush* acf) { |
1752 // All users of this draw state should be freeing up all effects when they'r
e done. | 1769 // All users of this draw state should be freeing up all effects when they'r
e done. |
1753 // Otherwise effects that own resources may keep those resources alive indef
initely. | 1770 // Otherwise effects that own resources may keep those resources alive indef
initely. |
1754 SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageSt
ages() && | 1771 SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageSt
ages() && |
1755 !fDrawState->hasGeometryProcessor()); | 1772 !fDrawState->hasGeometryProcessor()); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1954 fResourceCache->printStats(); | 1971 fResourceCache->printStats(); |
1955 } | 1972 } |
1956 #endif | 1973 #endif |
1957 | 1974 |
1958 #if GR_GPU_STATS | 1975 #if GR_GPU_STATS |
1959 const GrContext::GPUStats* GrContext::gpuStats() const { | 1976 const GrContext::GPUStats* GrContext::gpuStats() const { |
1960 return fGpu->gpuStats(); | 1977 return fGpu->gpuStats(); |
1961 } | 1978 } |
1962 #endif | 1979 #endif |
1963 | 1980 |
OLD | NEW |