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. | |
1379 } | 1377 } |
1380 | 1378 |
1381 bool GrContext::readTexturePixels(GrTexture* texture, | 1379 bool GrContext::readTexturePixels(GrTexture* texture, |
1382 int left, int top, int width, int height, | 1380 int left, int top, int width, int height, |
1383 GrPixelConfig config, void* buffer, size_t row
Bytes, | 1381 GrPixelConfig config, void* buffer, size_t row
Bytes, |
1384 uint32_t flags) { | 1382 uint32_t flags) { |
1385 ASSERT_OWNED_RESOURCE(texture); | 1383 ASSERT_OWNED_RESOURCE(texture); |
1386 | 1384 |
1387 GrRenderTarget* target = texture->asRenderTarget(); | 1385 GrRenderTarget* target = texture->asRenderTarget(); |
1388 if (target) { | 1386 if (target) { |
1389 return this->readRenderTargetPixels(target, | 1387 return this->readRenderTargetPixels(target, |
1390 left, top, width, height, | 1388 left, top, width, height, |
1391 config, buffer, rowBytes, | 1389 config, buffer, rowBytes, |
1392 flags); | 1390 flags); |
1393 } else { | 1391 } else { |
1394 // TODO: make this more efficient for cases where we're reading the enti
re | 1392 // TODO: make this more efficient for cases where we're reading the enti
re |
1395 // texture, i.e., use GetTexImage() instead | 1393 // texture, i.e., use GetTexImage() instead |
1396 | 1394 |
1397 // create scratch rendertarget and read from that | 1395 // create scratch rendertarget and read from that |
1398 GrAutoScratchTexture ast; | 1396 GrAutoScratchTexture ast; |
1399 GrTextureDesc desc; | 1397 GrTextureDesc desc; |
1400 desc.fFlags = kRenderTarget_GrTextureFlagBit; | 1398 desc.fFlags = kRenderTarget_GrTextureFlagBit; |
1401 desc.fWidth = width; | 1399 desc.fWidth = width; |
1402 desc.fHeight = height; | 1400 desc.fHeight = height; |
1403 desc.fConfig = config; | 1401 desc.fConfig = config; |
1404 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | 1402 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
1405 ast.set(this, desc, kExact_ScratchTexMatch); | 1403 ast.set(this, desc, kExact_ScratchTexMatch); |
1406 GrTexture* dst = ast.texture(); | 1404 GrTexture* dst = ast.texture(); |
1407 if (dst && (target = dst->asRenderTarget())) { | 1405 if (dst && (target = dst->asRenderTarget())) { |
1408 this->copySurface(target, texture, SkIRect::MakeXYWH(top, left, widt
h, height), | 1406 this->copyTexture(texture, target, NULL); |
1409 SkIPoint::Make(0,0)); | |
1410 return this->readRenderTargetPixels(target, | 1407 return this->readRenderTargetPixels(target, |
1411 left, top, width, height, | 1408 left, top, width, height, |
1412 config, buffer, rowBytes, | 1409 config, buffer, rowBytes, |
1413 flags); | 1410 flags); |
1414 } | 1411 } |
1415 | 1412 |
1416 return false; | 1413 return false; |
1417 } | 1414 } |
1418 } | 1415 } |
1419 | 1416 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 ASSERT_OWNED_RESOURCE(renderTarget); | 1584 ASSERT_OWNED_RESOURCE(renderTarget); |
1588 AutoRestoreEffects are; | 1585 AutoRestoreEffects are; |
1589 AutoCheckFlush acf(this); | 1586 AutoCheckFlush acf(this); |
1590 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf); | 1587 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf); |
1591 if (NULL == target) { | 1588 if (NULL == target) { |
1592 return; | 1589 return; |
1593 } | 1590 } |
1594 target->discard(renderTarget); | 1591 target->discard(renderTarget); |
1595 } | 1592 } |
1596 | 1593 |
1597 void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe
ct, | 1594 void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint*
topLeft) { |
1598 const SkIPoint& dstPoint, uint32_t pixelOpsFlags) { | |
1599 if (NULL == src || NULL == dst) { | 1595 if (NULL == src || NULL == dst) { |
1600 return; | 1596 return; |
1601 } | 1597 } |
1602 ASSERT_OWNED_RESOURCE(src); | 1598 ASSERT_OWNED_RESOURCE(src); |
1603 ASSERT_OWNED_RESOURCE(dst); | 1599 ASSERT_OWNED_RESOURCE(dst); |
1604 | 1600 |
1605 // Since we're going to the draw target and not GPU, no need to check kNoFlu
sh | 1601 SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height()); |
1606 // here. | 1602 if (topLeft) { |
| 1603 srcRect.offset(*topLeft); |
| 1604 } |
| 1605 SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height()); |
| 1606 if (!srcRect.intersect(srcBounds)) { |
| 1607 return; |
| 1608 } |
1607 | 1609 |
1608 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL); | 1610 GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL); |
1609 if (NULL == target) { | 1611 if (NULL == target) { |
1610 return; | 1612 return; |
1611 } | 1613 } |
| 1614 SkIPoint dstPoint; |
| 1615 dstPoint.setZero(); |
1612 target->copySurface(dst, src, srcRect, dstPoint); | 1616 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 pixelOpsFlags) { | 1624 uint32_t flags) { |
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 & pixelOpsFlags) &
& | 1649 if (renderTarget->asTexture() && !(kUnpremul_PixelOpsFlag & flags) && |
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, pixelOpsFla
gs); | 1653 srcConfig, buffer, rowBytes, flags); |
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 & pixelOpsFlags) { | 1686 if (kUnpremul_PixelOpsFlag & flags) { |
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 pixelOpsFlags & ~kUnpremul_PixelOpsFlag)) { | 1727 flags & ~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 | |
1735 // This function can be called in the midst of drawing another object (e.g.,
when uploading a | 1734 // This function can be called in the midst of drawing another object (e.g.,
when uploading a |
1736 // SW-rasterized clip while issuing a draw). So we push the current geometry
state before | 1735 // SW-rasterized clip while issuing a draw). So we push the current geometry
state before |
1737 // drawing a rect to the render target. | 1736 // drawing a rect to the render target. |
1738 // The bracket ensures we pop the stack if we wind up flushing below. | 1737 GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL
, NULL); |
1739 { | 1738 GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::kRese
t_ASRInit, &matrix); |
1740 GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw,
NULL, NULL); | 1739 GrDrawState* drawState = drawTarget->drawState(); |
1741 GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::k
Reset_ASRInit, | 1740 drawState->addColorProcessor(fp); |
1742 &matrix); | 1741 drawState->setRenderTarget(renderTarget); |
1743 GrDrawState* drawState = drawTarget->drawState(); | 1742 drawState->disableState(GrDrawState::kClip_StateBit); |
1744 drawState->addColorProcessor(fp); | 1743 drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScala
r(height))); |
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 | |
1754 return true; | 1744 return true; |
1755 } | 1745 } |
1756 | |
1757 void GrContext::flushSurfaceWrites(GrSurface* surface) { | |
1758 if (surface->surfacePriv().hasPendingWrite()) { | |
1759 this->flush(); | |
1760 } | |
1761 } | |
1762 | |
1763 //////////////////////////////////////////////////////////////////////////////// | 1746 //////////////////////////////////////////////////////////////////////////////// |
1764 | 1747 |
1765 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, | 1748 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, |
1766 BufferedDraw buffered, | 1749 BufferedDraw buffered, |
1767 AutoRestoreEffects* are, | 1750 AutoRestoreEffects* are, |
1768 AutoCheckFlush* acf) { | 1751 AutoCheckFlush* acf) { |
1769 // All users of this draw state should be freeing up all effects when they'r
e done. | 1752 // All users of this draw state should be freeing up all effects when they'r
e done. |
1770 // Otherwise effects that own resources may keep those resources alive indef
initely. | 1753 // Otherwise effects that own resources may keep those resources alive indef
initely. |
1771 SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageSt
ages() && | 1754 SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageSt
ages() && |
1772 !fDrawState->hasGeometryProcessor()); | 1755 !fDrawState->hasGeometryProcessor()); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1971 fResourceCache->printStats(); | 1954 fResourceCache->printStats(); |
1972 } | 1955 } |
1973 #endif | 1956 #endif |
1974 | 1957 |
1975 #if GR_GPU_STATS | 1958 #if GR_GPU_STATS |
1976 const GrContext::GPUStats* GrContext::gpuStats() const { | 1959 const GrContext::GPUStats* GrContext::gpuStats() const { |
1977 return fGpu->gpuStats(); | 1960 return fGpu->gpuStats(); |
1978 } | 1961 } |
1979 #endif | 1962 #endif |
1980 | 1963 |
OLD | NEW |