Index: src/gpu/GrContext.cpp |
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp |
index 4d6b6b8d0c3e6427c680d471586f6664578f2785..14f90f93a06fd1c4fbce428808385c084117b205 100644 |
--- a/src/gpu/GrContext.cpp |
+++ b/src/gpu/GrContext.cpp |
@@ -1,4 +1,3 @@ |
- |
/* |
* Copyright 2011 Google Inc. |
* |
@@ -28,6 +27,7 @@ |
#include "GrResourceCache.h" |
#include "GrResourceProvider.h" |
#include "GrSoftwarePathRenderer.h" |
+#include "GrStencilAndCoverTextContext.h" |
#include "GrStrokeInfo.h" |
#include "GrSurfacePriv.h" |
#include "GrTextBlobCache.h" |
@@ -36,13 +36,14 @@ |
#include "GrVertices.h" |
#include "SkDashPathPriv.h" |
#include "SkConfig8888.h" |
-#include "SkGr.h" |
+#include "SkGrPriv.h" |
#include "SkRRect.h" |
#include "SkStrokeRec.h" |
#include "SkSurfacePriv.h" |
#include "SkTLazy.h" |
#include "SkTLS.h" |
#include "SkTraceEvent.h" |
+#include "SkTypes.h" |
#include "batches/GrBatch.h" |
@@ -65,9 +66,13 @@ void GrContext::DrawingMgr::init(GrContext* context) { |
void GrContext::DrawingMgr::cleanup() { |
SkSafeSetNull(fDrawTarget); |
+ delete fNVPRTextContext; |
+ fNVPRTextContext = nullptr; |
for (int i = 0; i < kNumPixelGeometries; ++i) { |
- SkSafeSetNull(fDrawContext[i][0]); |
- SkSafeSetNull(fDrawContext[i][1]); |
+ delete fTextContexts[i][0]; |
+ fTextContexts[i][0] = nullptr; |
+ delete fTextContexts[i][1]; |
+ fTextContexts[i][1] = nullptr; |
} |
} |
@@ -76,21 +81,7 @@ GrContext::DrawingMgr::~DrawingMgr() { |
} |
void GrContext::DrawingMgr::abandon() { |
- SkSafeSetNull(fDrawTarget); |
- for (int i = 0; i < kNumPixelGeometries; ++i) { |
- for (int j = 0; j < kNumDFTOptions; ++j) { |
- if (fDrawContext[i][j]) { |
- SkSafeSetNull(fDrawContext[i][j]->fDrawTarget); |
- SkSafeSetNull(fDrawContext[i][j]); |
- } |
- } |
- } |
-} |
- |
-void GrContext::DrawingMgr::purgeResources() { |
- if (fDrawTarget) { |
- fDrawTarget->purgeResources(); |
- } |
+ this->cleanup(); |
} |
void GrContext::DrawingMgr::reset() { |
@@ -105,21 +96,41 @@ void GrContext::DrawingMgr::flush() { |
} |
} |
-GrDrawContext* GrContext::DrawingMgr::drawContext(const SkSurfaceProps* surfaceProps) { |
+GrTextContext* GrContext::DrawingMgr::textContext(const SkSurfaceProps& props, |
+ GrRenderTarget* rt) { |
if (this->abandoned()) { |
return nullptr; |
} |
- const SkSurfaceProps props(SkSurfacePropsCopyOrDefault(surfaceProps)); |
- |
SkASSERT(props.pixelGeometry() < kNumPixelGeometries); |
- if (!fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()]) { |
- fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()] = |
- new GrDrawContext(fContext, fDrawTarget, props); |
+ bool useDIF = props.isUseDeviceIndependentFonts(); |
+ |
+ if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() && |
+ rt->isStencilBufferMultisampled()) { |
+ GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt); |
+ if (sb) { |
+ if (!fNVPRTextContext) { |
+ fNVPRTextContext = GrStencilAndCoverTextContext::Create(fContext, props); |
+ } |
+ |
+ return fNVPRTextContext; |
+ } |
+ } |
+ |
+ if (!fTextContexts[props.pixelGeometry()][useDIF]) { |
+ fTextContexts[props.pixelGeometry()][useDIF] = GrAtlasTextContext::Create(fContext, props); |
+ } |
+ |
+ return fTextContexts[props.pixelGeometry()][useDIF]; |
+} |
+ |
+GrDrawContext* GrContext::DrawingMgr::drawContext(GrRenderTarget* rt, |
+ const SkSurfaceProps* surfaceProps) { |
+ if (this->abandoned()) { |
+ return nullptr; |
} |
- // For now, everyone gets a faux creation ref |
- return SkRef(fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()]); |
+ return new GrDrawContext(fContext, rt, fDrawTarget, surfaceProps); |
} |
//////////////////////////////////////////////////////////////////////////////// |
@@ -243,8 +254,6 @@ void GrContext::resetContext(uint32_t state) { |
void GrContext::freeGpuResources() { |
this->flush(); |
- fDrawingMgr.purgeResources(); |
- |
fBatchFontCache->freeAll(); |
fLayerCache->freeAll(); |
// a path renderer may be holding onto resources |
@@ -320,20 +329,42 @@ bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t |
bool GrContext::writeSurfacePixels(GrSurface* surface, |
int left, int top, int width, int height, |
- GrPixelConfig srcConfig, const void* buffer, size_t rowBytes, |
+ GrPixelConfig srcConfig, const SkTArray<SkMipMapLevel>& texels, |
uint32_t pixelOpsFlags) { |
RETURN_FALSE_IF_ABANDONED |
ASSERT_OWNED_RESOURCE(surface); |
SkASSERT(surface); |
+ SkTArray<SkMipMapLevel> texelsCopy(texels); |
+ |
this->testPMConversionsIfNecessary(pixelOpsFlags); |
// Trim the params here so that if we wind up making a temporary surface it can be as small as |
// necessary and because GrGpu::getWritePixelsInfo requires it. |
- if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(), |
- GrBytesPerPixel(srcConfig), &left, &top, &width, |
- &height, &buffer, &rowBytes)) { |
- return false; |
+ for (int currentMipLevel = texelsCopy.count() - 1; currentMipLevel >= 0; currentMipLevel--) { |
+ // make sure the texelmap's size range is within int range |
+ if (texelsCopy[currentMipLevel].fWidth > SK_MaxS32 |
+ || texelsCopy[currentMipLevel].fHeight > SK_MaxS32) { |
+ return false; |
+ } |
+ int currentMipWidth = texelsCopy[currentMipLevel].fWidth; |
+ int currentMipHeight = texelsCopy[currentMipLevel].fHeight; |
+ |
+ SkMipMapLevel& currentMipMap = texelsCopy[currentMipLevel]; |
+ if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(), |
+ GrBytesPerPixel(srcConfig), &left, &top, |
+ ¤tMipWidth, ¤tMipHeight, |
+ ¤tMipMap.fTexels, |
+ ¤tMipMap.fRowBytes)) { |
+ return false; |
+ } |
+ |
+ // make sure the size range is within the texelmap's size range |
+ if (currentMipWidth < 0 || currentMipHeight < 0) { |
+ return false; |
+ } |
+ texelsCopy[currentMipLevel].fWidth = currentMipWidth; |
+ texelsCopy[currentMipLevel].fHeight = currentMipHeight; |
} |
bool applyPremulToSrc = false; |
@@ -352,7 +383,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
} |
GrGpu::WritePixelTempDrawInfo tempDrawInfo; |
- if (!fGpu->getWritePixelsInfo(surface, width, height, rowBytes, srcConfig, &drawPreference, |
+ if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference, |
&tempDrawInfo)) { |
return false; |
} |
@@ -378,8 +409,8 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
textureMatrix.setIDiv(tempTexture->width(), tempTexture->height()); |
GrPaint paint; |
if (applyPremulToSrc) { |
- fp.reset(this->createUPMToPMEffect(paint.getProcessorDataManager(), tempTexture, |
- tempDrawInfo.fSwapRAndB, textureMatrix)); |
+ fp.reset(this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwapRAndB, |
+ textureMatrix)); |
// If premultiplying was the only reason for the draw, fall back to a straight write. |
if (!fp) { |
if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) { |
@@ -391,8 +422,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
} |
if (tempTexture) { |
if (!fp) { |
- fp.reset(GrConfigConversionEffect::Create( |
- paint.getProcessorDataManager(), tempTexture, tempDrawInfo.fSwapRAndB, |
+ fp.reset(GrConfigConversionEffect::Create(tempTexture, tempDrawInfo.fSwapRAndB, |
GrConfigConversionEffect::kNone_PMConversion, textureMatrix)); |
if (!fp) { |
return false; |
@@ -404,30 +434,37 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
this->flush(); |
} |
if (applyPremulToSrc) { |
- size_t tmpRowBytes = 4 * width; |
- tmpPixels.reset(width * height); |
- if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, |
- tmpPixels.get())) { |
- return false; |
+ for (int currentMipLevel = texelsCopy.count() - 1; currentMipLevel >= 0; |
+ currentMipLevel--) { |
+ SkMipMapLevel& currentMipMap = texelsCopy[currentMipLevel]; |
+ int currentWidth = currentMipMap.fWidth; |
+ int currentHeight = currentMipMap.fHeight; |
+ size_t tmpRowBytes = 4 * currentWidth; |
+ tmpPixels.reset(currentWidth * currentHeight); |
+ if (!sw_convert_to_premul(srcConfig, currentWidth, currentHeight, |
+ currentMipMap.fRowBytes, |
+ currentMipMap.fTexels, tmpRowBytes, |
+ tmpPixels.get())) { |
+ return false; |
+ } |
+ currentMipMap.fRowBytes = tmpRowBytes; |
+ currentMipMap.fTexels = tmpPixels.get(); |
} |
- rowBytes = tmpRowBytes; |
- buffer = tmpPixels.get(); |
applyPremulToSrc = false; |
} |
if (!fGpu->writePixels(tempTexture, 0, 0, width, height, |
- tempDrawInfo.fTempSurfaceDesc.fConfig, buffer, |
- rowBytes)) { |
+ tempDrawInfo.fTempSurfaceDesc.fConfig, texelsCopy)) { |
return false; |
} |
SkMatrix matrix; |
matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); |
- SkAutoTUnref<GrDrawContext> drawContext(this->drawContext()); |
+ SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(renderTarget)); |
if (!drawContext) { |
return false; |
} |
paint.addColorFragmentProcessor(fp); |
SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); |
- drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, nullptr); |
+ drawContext->drawRect(GrClip::WideOpen(), paint, matrix, rect, nullptr); |
if (kFlushWrites_PixelOp & pixelOpsFlags) { |
this->flushSurfaceWrites(surface); |
@@ -436,21 +473,47 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, |
} |
if (!tempTexture) { |
if (applyPremulToSrc) { |
- size_t tmpRowBytes = 4 * width; |
- tmpPixels.reset(width * height); |
- if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes, |
- tmpPixels.get())) { |
- return false; |
+ for (int currentMipLevel = texelsCopy.count() - 1; currentMipLevel >= 0; |
+ currentMipLevel--) { |
+ SkMipMapLevel& currentMipMap = texelsCopy[currentMipLevel]; |
+ int currentMipWidth = currentMipMap.fWidth; |
+ int currentMipHeight = currentMipMap.fHeight; |
+ size_t tmpRowBytes = 4 * currentMipWidth; |
+ tmpPixels.reset(currentMipWidth * currentMipHeight); |
+ if (!sw_convert_to_premul(srcConfig, currentMipWidth, currentMipHeight, |
+ currentMipMap.fRowBytes, currentMipMap.fTexels, |
+ tmpRowBytes, tmpPixels.get())) { |
+ return false; |
+ } |
+ currentMipMap.fRowBytes = tmpRowBytes; |
+ currentMipMap.fTexels = tmpPixels.get(); |
} |
- rowBytes = tmpRowBytes; |
- buffer = tmpPixels.get(); |
applyPremulToSrc = false; |
} |
- return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes); |
+ return fGpu->writePixels(surface, left, top, width, height, srcConfig, texelsCopy); |
} |
return true; |
} |
+bool GrContext::writeSurfacePixels(GrSurface* surface, |
+ int left, int top, int width, int height, |
+ GrPixelConfig srcConfig, const void* buffer, size_t rowBytes, |
+ uint32_t pixelOpsFlags) { |
+ if (width <= 0 || height <= 0) { |
+ return false; |
+ } |
+ const uint32_t baseLevelWidth = width; |
+ const uint32_t baseLevelHeight = height; |
+ |
+ SkMipMapLevel level(buffer, rowBytes, baseLevelWidth, baseLevelHeight); |
+ const int mipLevelCount = 1; |
+ SkTArray<SkMipMapLevel> texels(mipLevelCount); |
+ texels.push_back(level); |
+ |
+ return this->writeSurfacePixels(surface, left, top, width, height, srcConfig, texels, |
+ pixelOpsFlags); |
+} |
+ |
bool GrContext::readSurfacePixels(GrSurface* src, |
int left, int top, int width, int height, |
GrPixelConfig dstConfig, void* buffer, size_t rowBytes, |
@@ -516,8 +579,7 @@ bool GrContext::readSurfacePixels(GrSurface* src, |
GrPaint paint; |
SkAutoTUnref<const GrFragmentProcessor> fp; |
if (unpremul) { |
- fp.reset(this->createPMToUPMEffect( |
- paint.getProcessorDataManager(), src->asTexture(), tempDrawInfo.fSwapRAndB, |
+ fp.reset(this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwapRAndB, |
textureMatrix)); |
if (fp) { |
unpremul = false; // we no longer need to do this on CPU after the read back. |
@@ -528,16 +590,14 @@ bool GrContext::readSurfacePixels(GrSurface* src, |
} |
} |
if (!fp && temp) { |
- fp.reset(GrConfigConversionEffect::Create( |
- paint.getProcessorDataManager(), src->asTexture(), tempDrawInfo.fSwapRAndB, |
+ fp.reset(GrConfigConversionEffect::Create(src->asTexture(), tempDrawInfo.fSwapRAndB, |
GrConfigConversionEffect::kNone_PMConversion, textureMatrix)); |
} |
if (fp) { |
paint.addColorFragmentProcessor(fp); |
SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); |
- SkAutoTUnref<GrDrawContext> drawContext(this->drawContext()); |
- drawContext->drawRect(temp->asRenderTarget(), GrClip::WideOpen(), paint, |
- SkMatrix::I(), rect, nullptr); |
+ SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(temp->asRenderTarget())); |
+ drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect, nullptr); |
surfaceToRead.reset(SkRef(temp.get())); |
left = 0; |
top = 0; |
@@ -611,12 +671,12 @@ void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe |
return; |
} |
- SkAutoTUnref<GrDrawContext> drawContext(this->drawContext()); |
+ SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(dst->asRenderTarget())); |
if (!drawContext) { |
return; |
} |
- drawContext->copySurface(dst->asRenderTarget(), src, srcRect, dstPoint); |
+ drawContext->copySurface(src, srcRect, dstPoint); |
if (kFlushWrites_PixelOp & pixelOpsFlags) { |
this->flush(); |
@@ -705,8 +765,7 @@ void GrContext::testPMConversionsIfNecessary(uint32_t flags) { |
} |
} |
-const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrProcessorDataManager* procDataManager, |
- GrTexture* texture, |
+const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture, |
bool swapRAndB, |
const SkMatrix& matrix) const { |
// We should have already called this->testPMConversionsIfNecessary(). |
@@ -714,15 +773,13 @@ const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrProcessorDataManager |
GrConfigConversionEffect::PMConversion pmToUPM = |
static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); |
if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { |
- return GrConfigConversionEffect::Create(procDataManager, texture, swapRAndB, pmToUPM, |
- matrix); |
+ return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix); |
} else { |
return nullptr; |
} |
} |
-const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrProcessorDataManager* procDataManager, |
- GrTexture* texture, |
+const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture, |
bool swapRAndB, |
const SkMatrix& matrix) const { |
// We should have already called this->testPMConversionsIfNecessary(). |
@@ -730,8 +787,7 @@ const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrProcessorDataManager |
GrConfigConversionEffect::PMConversion upmToPM = |
static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); |
if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { |
- return GrConfigConversionEffect::Create(procDataManager, texture, swapRAndB, upmToPM, |
- matrix); |
+ return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix); |
} else { |
return nullptr; |
} |